From bf2fff44b82dd1a75d29278b9666592db3ab653d Mon Sep 17 00:00:00 2001 From: Sebastien L Date: Thu, 12 Feb 2026 04:48:38 +0000 Subject: [PATCH] style: apply clang-format and enforce left pointer alignment --- .clang-format | 2 +- components/_override/esp32/i2s.c | 690 ++++---- components/audio/inc/esp_equalizer.h | 15 +- components/audio/link_helper.c | 4 +- components/display/ILI9341.c | 589 ++++--- components/display/SH1106.c | 252 +-- components/display/SSD1306.c | 273 +-- components/display/SSD1322.c | 329 ++-- components/display/SSD132x.c | 583 +++---- components/display/SSD1351.c | 464 ++--- components/display/SSD1675.c | 469 +++-- components/display/ST77xx.c | 493 +++--- components/display/core/gds.c | 422 ++--- components/display/core/gds.h | 54 +- components/display/core/gds_default_if.h | 8 +- components/display/core/gds_draw.c | 563 +++--- components/display/core/gds_draw.h | 18 +- components/display/core/gds_err.h | 49 +- components/display/core/gds_font.c | 289 ++-- components/display/core/gds_font.h | 57 +- components/display/core/gds_image.c | 658 ++++--- components/display/core/gds_image.h | 26 +- components/display/core/gds_private.h | 257 ++- components/display/core/gds_text.c | 288 ++-- components/display/core/gds_text.h | 43 +- .../display/core/ifaces/default_if_i2c.c | 108 +- .../display/core/ifaces/default_if_spi.c | 120 +- components/display/display.c | 791 +++++---- components/display/display.h | 19 +- components/driver_bt/bt_app_core.c | 53 +- components/driver_bt/bt_app_core.h | 3 +- components/driver_bt/bt_app_sink.c | 590 +++---- components/driver_bt/bt_app_sink.h | 19 +- components/driver_bt/bt_app_source.c | 964 +++++------ components/led_strip/led_strip.c | 224 +-- components/led_strip/led_strip.h | 18 +- components/led_strip/led_vu.c | 223 ++- components/led_strip/led_vu.h | 13 +- components/metrics/Batch.cpp | 42 +- components/metrics/Events.cpp | 37 +- components/metrics/Events.h | 5 +- components/metrics/Metrics.cpp | 34 +- components/metrics/http_handlers.c | 63 +- components/platform_config/Config.cpp | 91 +- components/platform_config/Config.h | 11 +- components/platform_config/Locking.cpp | 10 +- components/platform_config/Locking.h | 2 +- components/platform_config/PBW.cpp | 142 +- components/platform_config/PBW.h | 103 +- components/platform_config/WifiList.cpp | 334 ++-- components/platform_config/WifiList.h | 34 +- .../test/test_platform_config.cpp | 108 +- .../platform_console/app_recovery/recovery.c | 34 +- .../app_squeezelite/cmd_squeezelite.c | 38 +- components/platform_console/cmd_config.c | 202 +-- components/platform_console/cmd_i2ctools.c | 652 +++---- components/platform_console/cmd_i2ctools.h | 2 +- components/platform_console/cmd_ota.c | 43 +- components/platform_console/cmd_ota.h | 2 +- components/platform_console/cmd_system.c | 225 +-- components/platform_console/cmd_system.h | 2 +- components/platform_console/cmd_wifi.c | 129 +- .../platform_console/platform_console.c | 118 +- .../platform_console/platform_console.h | 20 +- .../platform_console/test/test_system.c | 167 +- components/raop/dmap_parser.c | 754 +++----- components/raop/dmap_parser.h | 48 +- components/raop/log_util.h | 20 +- components/raop/platform.h | 72 +- components/raop/raop.c | 1512 ++++++++--------- components/raop/raop.h | 10 +- components/raop/raop_sink.c | 215 ++- components/raop/raop_sink.h | 29 +- components/raop/rtp.c | 1098 ++++++------ components/raop/rtp.h | 21 +- components/raop/util.c | 689 ++++---- components/raop/util.h | 102 +- components/services/accessors.c | 169 +- components/services/accessors.h | 87 +- components/services/audio_controls.c | 145 +- components/services/audio_controls.h | 34 +- components/services/battery.c | 73 +- components/services/battery.h | 1 - components/services/buttons.c | 100 +- components/services/buttons.h | 28 +- components/services/globdefs.h | 6 +- components/services/gpio_exp.c | 964 ++++++----- components/services/gpio_exp.h | 81 +- components/services/infrared.c | 195 +-- components/services/infrared.h | 5 +- components/services/led.c | 120 +- components/services/led.h | 12 +- components/services/messaging.c | 95 +- components/services/messaging.h | 68 +- components/services/monitor.c | 244 ++- components/services/rotary_encoder.c | 182 +- components/services/rotary_encoder.h | 50 +- components/services/services.c | 176 +- components/services/services.h | 4 +- components/services/system_time.c | 7 +- components/spotify/Shim.cpp | 194 +-- components/spotify/cspot_private.h | 8 +- components/spotify/cspot_sink.c | 212 +-- components/spotify/cspot_sink.h | 33 +- components/squeezelite-ota/squeezelite-ota.c | 1093 ++++++------ components/squeezelite-ota/squeezelite-ota.h | 5 +- components/targets/muse/muse.c | 134 +- components/targets/targets.c | 19 +- components/targets/targets.h | 14 +- components/telnet/telnet.c | 46 +- components/telnet/telnet.h | 2 +- components/tools/bootstate.cpp | 40 +- components/tools/bootstate.h | 2 - components/tools/cpp_tools.cpp | 8 +- components/tools/operator.cpp | 8 +- components/tools/perf_trace.h | 119 +- components/tools/platform_esp32.h | 4 +- components/tools/tcpip_adapter_compat.h | 35 +- components/tools/test/test_tools.cpp | 29 +- components/tools/tools.c | 88 +- components/tools/tools.h | 4 +- components/tools/tools_http_utils.c | 34 +- components/tools/tools_http_utils.h | 4 - components/tools/tools_spiffs_utils.cpp | 129 +- components/tools/trace.c | 13 +- components/tools/trace.h | 10 +- components/wifi-manager/dns_server.c | 94 +- components/wifi-manager/dns_server.h | 118 +- .../wifi-manager/http_server_handlers.c | 413 ++--- .../wifi-manager/http_server_handlers.h | 12 +- .../wifi-manager/network_driver_DM9051.c | 22 +- .../wifi-manager/network_driver_LAN8720.c | 26 +- .../wifi-manager/network_driver_W5500.c | 35 +- components/wifi-manager/network_ethernet.c | 44 +- components/wifi-manager/network_ethernet.h | 14 +- components/wifi-manager/network_manager.c | 189 +-- components/wifi-manager/network_manager.h | 216 ++- .../wifi-manager/network_manager_handlers.c | 152 +- components/wifi-manager/network_services.h | 72 +- components/wifi-manager/network_status.cpp | 64 +- components/wifi-manager/network_status.h | 3 - components/wifi-manager/network_wifi.cpp | 225 ++- components/wifi-manager/network_wifi.h | 32 +- .../wifi-manager/wifi_manager_http_server.c | 188 +- main/esp_app_main.c | 40 +- main/platform_esp32.h | 10 +- test/test_main/test_common_init.c | 23 +- test/test_main/test_runner.c | 27 +- 148 files changed, 11508 insertions(+), 12904 deletions(-) diff --git a/.clang-format b/.clang-format index db4d66d8..5d2c8d75 100644 --- a/.clang-format +++ b/.clang-format @@ -4,7 +4,7 @@ UseTab: Never IndentWidth: 4 TabWidth: 4 ColumnLimit: 150 -PointerAlignment: Right +PointerAlignment: Left ReferenceAlignment: Pointer AlignAfterOpenBracket: DontAlign BreakBeforeBraces: Attach diff --git a/components/_override/esp32/i2s.c b/components/_override/esp32/i2s.c index 654a36be..f6896c66 100644 --- a/components/_override/esp32/i2s.c +++ b/components/_override/esp32/i2s.c @@ -46,36 +46,37 @@ static const char* I2S_TAG = "I2S"; -#define I2S_CHECK(a, str, ret) if (!(a)) { \ - ESP_LOGE(I2S_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret); \ - } +#define I2S_CHECK(a, str, ret) \ + if(!(a)) { \ + ESP_LOGE(I2S_TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret); \ + } -#define I2S_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) -#define I2S_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) -#define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) -#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) +#define I2S_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) +#define I2S_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) +#define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num]) +#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) +#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) +#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) //TODO: Refactor to put this logic into LL -#define I2S_AD_BCK_FACTOR (2) -#define I2S_PDM_BCK_FACTOR (64) -#define I2S_BASE_CLK (2*APB_CLK_FREQ) -#define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware +#define I2S_AD_BCK_FACTOR (2) +#define I2S_PDM_BCK_FACTOR (64) +#define I2S_BASE_CLK (2 * APB_CLK_FREQ) +#define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware /** * @brief DMA buffer object * */ typedef struct { - char **buf; + char** buf; int buf_size; int rw_pos; - void *curr_ptr; + void* curr_ptr; SemaphoreHandle_t mux; xQueueHandle queue; - lldesc_t **desc; + lldesc_t** desc; } i2s_dma_t; /** @@ -83,30 +84,30 @@ typedef struct { * */ typedef struct { - i2s_port_t i2s_num; /*!< I2S port number*/ - int queue_size; /*!< I2S event queue size*/ - QueueHandle_t i2s_queue; /*!< I2S queue handler*/ - int dma_buf_count; /*!< DMA buffer count, number of buffer*/ - int dma_buf_len; /*!< DMA buffer length, length of each buffer*/ - i2s_dma_t *rx; /*!< DMA Tx buffer*/ - i2s_dma_t *tx; /*!< DMA Rx buffer*/ + i2s_port_t i2s_num; /*!< I2S port number*/ + int queue_size; /*!< I2S event queue size*/ + QueueHandle_t i2s_queue; /*!< I2S queue handler*/ + int dma_buf_count; /*!< DMA buffer count, number of buffer*/ + int dma_buf_len; /*!< DMA buffer length, length of each buffer*/ + i2s_dma_t* rx; /*!< DMA Tx buffer*/ + i2s_dma_t* tx; /*!< DMA Rx buffer*/ i2s_isr_handle_t i2s_isr_handle; /*!< I2S Interrupt handle*/ - int channel_num; /*!< Number of channels*/ - int bytes_per_sample; /*!< Bytes per sample*/ - int bits_per_sample; /*!< Bits per sample*/ - i2s_mode_t mode; /*!< I2S Working mode*/ - uint32_t sample_rate; /*!< I2S sample rate */ - bool use_apll; /*!< I2S use APLL clock */ - bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */ - int fixed_mclk; /*!< I2S fixed MLCK clock */ + int channel_num; /*!< Number of channels*/ + int bytes_per_sample; /*!< Bytes per sample*/ + int bits_per_sample; /*!< Bits per sample*/ + i2s_mode_t mode; /*!< I2S Working mode*/ + uint32_t sample_rate; /*!< I2S sample rate */ + bool use_apll; /*!< I2S use APLL clock */ + bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */ + int fixed_mclk; /*!< I2S fixed MLCK clock */ double real_rate; #ifdef CONFIG_PM_ENABLE esp_pm_lock_handle_t pm_lock; #endif - i2s_hal_context_t hal; /*!< I2S hal context*/ + i2s_hal_context_t hal; /*!< I2S hal context*/ } i2s_obj_t; -static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0}; +static i2s_obj_t* p_i2s_obj[I2S_NUM_MAX] = {0}; static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX]; #if SOC_I2S_SUPPORTS_ADC_DAC @@ -114,22 +115,20 @@ static int _i2s_adc_unit = -1; static int _i2s_adc_channel = -1; #endif -static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len); -static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma); +static i2s_dma_t* i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len); +static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t* dma); -static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) -{ +static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) { //if pin = -1, do not need to configure - if (gpio != -1) { + if(gpio != -1) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); gpio_set_direction(gpio, GPIO_MODE_OUTPUT); esp_rom_gpio_connect_out_signal(gpio, signal_idx, out_inv, oen_inv); } } -static inline void gpio_matrix_in_check(int gpio, uint32_t signal_idx, bool inv) -{ - if (gpio != -1) { +static inline void gpio_matrix_in_check(int gpio, uint32_t signal_idx, bool inv) { + if(gpio != -1) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); //Set direction, for some GPIOs, the input function are not enabled as default. gpio_set_direction(gpio, GPIO_MODE_INPUT); @@ -137,15 +136,13 @@ static inline void gpio_matrix_in_check(int gpio, uint32_t signal_idx, bool inv) } } -esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask) -{ +esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), clr_mask); return ESP_OK; } -esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) -{ +esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); i2s_hal_enable_rx_intr(&(p_i2s_obj[i2s_num]->hal)); @@ -153,58 +150,50 @@ esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) return ESP_OK; } -esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num) -{ +esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); i2s_hal_disable_rx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } -esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num) -{ +esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); i2s_hal_disable_tx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } -esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num) -{ +esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); i2s_hal_enable_tx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } -float i2s_get_clk(i2s_port_t i2s_num) -{ +float i2s_get_clk(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); return p_i2s_obj[i2s_num]->real_rate; } -static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle) -{ +static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void* arg, i2s_isr_handle_t* handle) { return esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_alloc_flags, fn, arg, handle); } -static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) -{ +static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) { int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000; #if CONFIG_IDF_TARGET_ESP32 /* ESP32 rev0 silicon issue for APLL range/accuracy, please see ESP32 ECO document for more information on this */ - if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + if(!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { sdm0 = 0; sdm1 = 0; } #endif float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4); - if (fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) { - return SOC_I2S_APLL_MAX_FREQ; - } - float fpll = fout / (2 * (odir+2)); //== fi2s (N=1, b=0, a=1) - return fpll/2; + if(fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) { return SOC_I2S_APLL_MAX_FREQ; } + float fpll = fout / (2 * (odir + 2)); //== fi2s (N=1, b=0, a=1) + return fpll / 2; } /** @@ -241,65 +230,69 @@ static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2 * @return ESP_ERR_INVALID_ARG or ESP_OK */ -static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir) - { - int _odir, _sdm0, _sdm1, _sdm2; - float r = rtc_clk_xtal_freq_get() * 1000000. / (rate * 2 * 2); - int _sdm2_max; - uint32_t prec = -1; - int o, s1, s0; +static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int* sdm0, int* sdm1, int* sdm2, int* odir) { + int _odir, _sdm0, _sdm1, _sdm2; + float r = rtc_clk_xtal_freq_get() * 1000000. / (rate * 2 * 2); + int _sdm2_max; + uint32_t prec = -1; + int o, s1, s0; - if (rate/bits_per_sample/2/8 < APLL_I2S_MIN_RATE) { - return ESP_ERR_INVALID_ARG; + if(rate / bits_per_sample / 2 / 8 < APLL_I2S_MIN_RATE) { return ESP_ERR_INVALID_ARG; } + + *sdm0 = 0; + *sdm1 = 0; + *sdm2 = 0; + *odir = 0; + + _sdm2 = 1 / r * 2 - 4; + if(_sdm2 < 4) _sdm2 = 4; + _sdm2_max = ceil(1 / r * (31 + 2) - (255 / 256 + 255 / 65536 + 4)); + if(_sdm2_max > 8) _sdm2_max = 8; + + // explore up to 5 sdm2 values + for(; _sdm2 < _sdm2_max; _sdm2++) { + _odir = r * (_sdm2 + 4) - 2; + if(_odir < 0) + _odir = 0; + else if(_odir > 31) + _odir = 31; + + for(o = 0; o < 2 && _odir + o < 32; o++) { + _sdm1 = 256 * ((_odir + o + 2) / r - (_sdm2 + 4)); + if(_sdm1 < 0) + _sdm1 = 0; + else if(_sdm1 > 255) + _sdm1 = 255; + + for(s1 = 0; s1 < 2 && _sdm1 + s1 < 256; s1++) { + _sdm0 = 65536 * ((_odir + o + 2) / r - (_sdm2 + (float)(_sdm1 + s1) / 256 + 4)); + if(_sdm0 < 0) + _sdm1 = 0; + else if(_sdm0 > 255) + _sdm0 = 255; + + for(s0 = 0; s0 < 2 && _sdm2 + s0 < 256; s0++) { + int _fi2s = i2s_apll_get_fi2s(bits_per_sample, _sdm0 + s0, _sdm1 + s1, _sdm2, _odir + o); + if(abs(_fi2s - rate) < prec) { + prec = abs(_fi2s - rate); + *sdm0 = _sdm0 + s0; + *sdm1 = _sdm1 + s1; + *sdm2 = _sdm2; + *odir = _odir + o; + } + } + } + } } - *sdm0 = 0; - *sdm1 = 0; - *sdm2 = 0; - *odir = 0; - - _sdm2 = 1/r * 2 - 4; - if (_sdm2 < 4) _sdm2 = 4; - _sdm2_max = ceil(1/r * (31 + 2) - (255/256 + 255/65536 + 4)); - if (_sdm2_max > 8) _sdm2_max = 8; - - // explore up to 5 sdm2 values - for (; _sdm2 < _sdm2_max; _sdm2++) { - _odir = r * (_sdm2 + 4) - 2; - if (_odir < 0) _odir = 0; - else if (_odir > 31) _odir = 31; - - for (o = 0; o < 2 && _odir + o < 32; o++) { - _sdm1 = 256*((_odir + o + 2) / r - (_sdm2 + 4)); - if (_sdm1 < 0) _sdm1 = 0; - else if (_sdm1 > 255) _sdm1 = 255; - - for (s1 = 0; s1 < 2 && _sdm1 + s1 < 256; s1++) { - _sdm0 = 65536*((_odir + o + 2) / r - (_sdm2 + (float) (_sdm1 + s1)/256 + 4)); - if (_sdm0 < 0) _sdm1 = 0; - else if (_sdm0 > 255) _sdm0 = 255; - - for (s0 = 0; s0 < 2 && _sdm2 + s0 < 256; s0++) { - int _fi2s = i2s_apll_get_fi2s(bits_per_sample, _sdm0 + s0, _sdm1 + s1, _sdm2, _odir + o); - if (abs(_fi2s - rate) < prec) { - prec = abs(_fi2s - rate); - *sdm0 = _sdm0 + s0; - *sdm1 = _sdm1 + s1; - *sdm2 = _sdm2; - *odir = _odir + o; - } - } - } - } - } - - if (*sdm2 + *sdm0 + *sdm0 + *odir) return ESP_OK; - else return ESP_ERR_INVALID_ARG; + if(*sdm2 + *sdm0 + *sdm0 + *odir) + return ESP_OK; + else + return ESP_ERR_INVALID_ARG; } -esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch) -{ - int factor = (256%bits)? 384 : 256; // According to hardware codec requirement(supported 256fs or 384fs) +esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch) { + int factor = (256 % bits) ? 384 : 256; // According to hardware codec requirement(supported 256fs or 384fs) int clkmInteger, clkmDecimals, bck = 0; double denom = (double)1 / 64; int channel = 2; @@ -307,12 +300,12 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (bits % 8 != 0 || bits > I2S_BITS_PER_SAMPLE_32BIT || bits < I2S_BITS_PER_SAMPLE_16BIT) { + if(bits % 8 != 0 || bits > I2S_BITS_PER_SAMPLE_32BIT || bits < I2S_BITS_PER_SAMPLE_16BIT) { ESP_LOGE(I2S_TAG, "Invalid bits per sample"); return ESP_ERR_INVALID_ARG; } - if (p_i2s_obj[i2s_num] == NULL) { + if(p_i2s_obj[i2s_num] == NULL) { ESP_LOGE(I2S_TAG, "Not initialized yet"); return ESP_ERR_INVALID_ARG; } @@ -322,40 +315,34 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b * Due to hardware issue, bck division on ESP32/ESP32-S2 should be greater than 8 in slave mode * So the factor need to be an appropriate value */ - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) && !p_i2s_obj[i2s_num]->use_apll) { - factor = 64 * bits; - } + if((p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) && !p_i2s_obj[i2s_num]->use_apll) { factor = 64 * bits; } double clkmdiv = (double)I2S_BASE_CLK / (rate * factor); - if (clkmdiv > 256) { + if(clkmdiv > 256) { ESP_LOGE(I2S_TAG, "clkmdiv is too large\r\n"); return ESP_ERR_INVALID_ARG; } // wait all on-going writing finish - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { + if((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); } - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { + if((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); } i2s_stop(i2s_num); #if SOC_I2S_SUPPORTS_ADC_DAC /* I2S-ADC only support single channel format. */ - if (!(p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN)) { - i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); - } + if(!(p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN)) { i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); } #else i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); #endif i2s_hal_set_tx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); - if (p_i2s_obj[i2s_num]->channel_num != (int)ch) { - p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1; - } + if(p_i2s_obj[i2s_num]->channel_num != (int)ch) { p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1; } - if ((int)bits != p_i2s_obj[i2s_num]->bits_per_sample) { + if((int)bits != p_i2s_obj[i2s_num]->bits_per_sample) { p_i2s_obj[i2s_num]->bits_per_sample = bits; // Round bytes_per_sample up to next multiple of 16 bits @@ -363,53 +350,50 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b p_i2s_obj[i2s_num]->bytes_per_sample = halfwords_per_sample * 2; // Because limited of DMA buffer is 4092 bytes - if (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num > 4092) { + if(p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num > 4092) { p_i2s_obj[i2s_num]->dma_buf_len = 4092 / p_i2s_obj[i2s_num]->bytes_per_sample / p_i2s_obj[i2s_num]->channel_num; } // Re-create TX DMA buffer - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { save_tx = p_i2s_obj[i2s_num]->tx; p_i2s_obj[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len); - if (p_i2s_obj[i2s_num]->tx == NULL) { + if(p_i2s_obj[i2s_num]->tx == NULL) { ESP_LOGE(I2S_TAG, "Failed to create tx dma buffer"); i2s_driver_uninstall(i2s_num); return ESP_ERR_NO_MEM; } - i2s_hal_set_out_link_addr(&(p_i2s_obj[i2s_num]->hal), (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0]); + i2s_hal_set_out_link_addr(&(p_i2s_obj[i2s_num]->hal), (uint32_t)p_i2s_obj[i2s_num]->tx->desc[0]); //destroy old tx dma if exist - if (save_tx) { - i2s_destroy_dma_queue(i2s_num, save_tx); - } + if(save_tx) { i2s_destroy_dma_queue(i2s_num, save_tx); } } // Re-create RX DMA buffer - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { save_rx = p_i2s_obj[i2s_num]->rx; p_i2s_obj[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len); - if (p_i2s_obj[i2s_num]->rx == NULL){ + if(p_i2s_obj[i2s_num]->rx == NULL) { ESP_LOGE(I2S_TAG, "Failed to create rx dma buffer"); i2s_driver_uninstall(i2s_num); return ESP_ERR_NO_MEM; } - i2s_hal_set_in_link(&(p_i2s_obj[i2s_num]->hal), p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample, (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0]); + i2s_hal_set_in_link(&(p_i2s_obj[i2s_num]->hal), + p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample, + (uint32_t)p_i2s_obj[i2s_num]->rx->desc[0]); //destroy old rx dma if exist - if (save_rx) { - i2s_destroy_dma_queue(i2s_num, save_rx); - } + if(save_rx) { i2s_destroy_dma_queue(i2s_num, save_rx); } } - } double mclk; //int sdm0, sdm1, sdm2, odir, m_scale = 8; - int sdm0, sdm1, sdm2, odir, m_scale = (rate > 96000 && bits > 16) ? 4 : 8; - int fi2s_clk = rate*channel*bits*m_scale; + int sdm0, sdm1, sdm2, odir, m_scale = (rate > 96000 && bits > 16) ? 4 : 8; + int fi2s_clk = rate * channel * bits * m_scale; #if SOC_I2S_SUPPORTS_ADC_DAC - if (p_i2s_obj[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + if(p_i2s_obj[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { //DAC uses bclk as sample clock, not WS. WS can be something arbitrary. //Rate as given to this function is the intended sample rate; @@ -418,15 +402,15 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b fi2s_clk /= I2S_AD_BCK_FACTOR; int factor2 = 60; mclk = b_clk * factor2; - clkmdiv = ((double) I2S_BASE_CLK) / mclk; + clkmdiv = ((double)I2S_BASE_CLK) / mclk; clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; #endif #if SOC_I2S_SUPPORTS_PDM - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_PDM) { + } else if(p_i2s_obj[i2s_num]->mode & I2S_MODE_PDM) { uint32_t b_clk = 0; - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { uint32_t fp, fs; i2s_hal_get_tx_pdm(&(p_i2s_obj[i2s_num]->hal), &fp, &fs); // Recommended set `fp = 960, fs = sample_rate / 100` @@ -434,15 +418,15 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b i2s_hal_tx_pdm_cfg(&(p_i2s_obj[i2s_num]->hal), fp, fs); b_clk = rate * I2S_PDM_BCK_FACTOR * fp / fs; - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + } else if(p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { uint32_t dsr; i2s_hal_get_rx_pdm(&(p_i2s_obj[i2s_num]->hal), &dsr); b_clk = rate * I2S_PDM_BCK_FACTOR * (dsr ? 2 : 1); } fi2s_clk = b_clk * m_scale; - int factor2 = 5 ; + int factor2 = 5; mclk = b_clk * factor2; - clkmdiv = ((double) I2S_BASE_CLK) / mclk; + clkmdiv = ((double)I2S_BASE_CLK) / mclk; clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; @@ -452,12 +436,12 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; mclk = clkmInteger + denom * clkmDecimals; - bck = factor/(bits * channel); + bck = factor / (bits * channel); } if(p_i2s_obj[i2s_num]->use_apll && p_i2s_obj[i2s_num]->fixed_mclk) { fi2s_clk = p_i2s_obj[i2s_num]->fixed_mclk; - m_scale = fi2s_clk/bits/rate/channel; + m_scale = fi2s_clk / bits / rate / channel; } if(p_i2s_obj[i2s_num]->use_apll && i2s_apll_calculate_fi2s(fi2s_clk, bits, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) { ESP_LOGD(I2S_TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); @@ -465,22 +449,22 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b i2s_hal_set_clk_div(&(p_i2s_obj[i2s_num]->hal), 1, 1, 0, m_scale, m_scale); i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_APLL); double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir); - p_i2s_obj[i2s_num]->real_rate = fi2s_rate/bits/channel/m_scale; - ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", - rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0); + p_i2s_obj[i2s_num]->real_rate = fi2s_rate / bits / channel / m_scale; + ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", rate, + fi2s_rate / bits / channel / m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate / 8, 1, 0); } else { i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_D2CLK); i2s_hal_set_clk_div(&(p_i2s_obj[i2s_num]->hal), clkmInteger, 63, clkmDecimals, bck, bck); - double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2); + double real_rate = (double)(I2S_BASE_CLK / (bck * bits * clkmInteger) / 2); p_i2s_obj[i2s_num]->real_rate = real_rate; - ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", - rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals); + ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", rate, + real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate * bits * channel, 64, clkmDecimals); } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { p_i2s_obj[i2s_num]->tx->curr_ptr = NULL; p_i2s_obj[i2s_num]->tx->rw_pos = 0; } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { p_i2s_obj[i2s_num]->rx->curr_ptr = NULL; p_i2s_obj[i2s_num]->rx->rw_pos = 0; } @@ -489,19 +473,14 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b i2s_hal_set_rx_bits_mod(&(p_i2s_obj[i2s_num]->hal), bits); // wait all writing on-going finish - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { - xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); - } - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { - xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); - } + if((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); } + if((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); } i2s_start(i2s_num); return ESP_OK; } -static void IRAM_ATTR i2s_intr_handler_default(void *arg) -{ - i2s_obj_t *p_i2s = (i2s_obj_t*) arg; +static void IRAM_ATTR i2s_intr_handler_default(void* arg) { + i2s_obj_t* p_i2s = (i2s_obj_t*)arg; uint32_t status; i2s_hal_get_intr_status(&(p_i2s->hal), &status); if(status == 0) { @@ -514,116 +493,96 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) portBASE_TYPE high_priority_task_awoken = 0; - lldesc_t *finish_desc = NULL; + lldesc_t* finish_desc = NULL; - if ((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) { + if((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) { ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", status); - if (p_i2s->i2s_queue) { + if(p_i2s->i2s_queue) { i2s_event.type = I2S_EVENT_DMA_ERROR; - if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { - xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); - } - xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + if(xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); } + xQueueSendFromISR(p_i2s->i2s_queue, (void*)&i2s_event, &high_priority_task_awoken); } } - if ((status & I2S_INTR_OUT_EOF) && p_i2s->tx) { - i2s_hal_get_out_eof_des_addr(&(p_i2s->hal), (uint32_t *)&finish_desc); + if((status & I2S_INTR_OUT_EOF) && p_i2s->tx) { + i2s_hal_get_out_eof_des_addr(&(p_i2s->hal), (uint32_t*)&finish_desc); // All buffers are empty. This means we have an underflow on our hands. - if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { + if(xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken); // See if tx descriptor needs to be auto cleared: // This will avoid any kind of noise that may get introduced due to transmission // of previous data from tx descriptor on I2S line. - if (p_i2s->tx_desc_auto_clear == true) { - memset((void *) dummy, 0, p_i2s->tx->buf_size); - } + if(p_i2s->tx_desc_auto_clear == true) { memset((void*)dummy, 0, p_i2s->tx->buf_size); } } xQueueSendFromISR(p_i2s->tx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken); - if (p_i2s->i2s_queue) { + if(p_i2s->i2s_queue) { i2s_event.type = I2S_EVENT_TX_DONE; - if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { - xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); - } - xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + if(xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); } + xQueueSendFromISR(p_i2s->i2s_queue, (void*)&i2s_event, &high_priority_task_awoken); } } - if ((status & I2S_INTR_IN_SUC_EOF) && p_i2s->rx) { + if((status & I2S_INTR_IN_SUC_EOF) && p_i2s->rx) { // All buffers are full. This means we have an overflow. - i2s_hal_get_in_eof_des_addr(&(p_i2s->hal), (uint32_t *)&finish_desc); - if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { - xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); - } + i2s_hal_get_in_eof_des_addr(&(p_i2s->hal), (uint32_t*)&finish_desc); + if(xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); } xQueueSendFromISR(p_i2s->rx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken); - if (p_i2s->i2s_queue) { + if(p_i2s->i2s_queue) { i2s_event.type = I2S_EVENT_RX_DONE; - if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + if(p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); } - xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + xQueueSendFromISR(p_i2s->i2s_queue, (void*)&i2s_event, &high_priority_task_awoken); } } i2s_hal_clear_intr_status(&(p_i2s->hal), status); - if (high_priority_task_awoken == pdTRUE) { - portYIELD_FROM_ISR(); - } + if(high_priority_task_awoken == pdTRUE) { portYIELD_FROM_ISR(); } } -static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) -{ +static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t* dma) { int bux_idx; - if (p_i2s_obj[i2s_num] == NULL) { + if(p_i2s_obj[i2s_num] == NULL) { ESP_LOGE(I2S_TAG, "Not initialized yet"); return ESP_ERR_INVALID_ARG; } - if (dma == NULL) { + if(dma == NULL) { ESP_LOGE(I2S_TAG, "dma is NULL"); return ESP_ERR_INVALID_ARG; } - for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) { - if (dma->desc && dma->desc[bux_idx]) { - free(dma->desc[bux_idx]); - } - if (dma->buf && dma->buf[bux_idx]) { - free(dma->buf[bux_idx]); - } - } - if (dma->buf) { - free(dma->buf); - } - if (dma->desc) { - free(dma->desc); + for(bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) { + if(dma->desc && dma->desc[bux_idx]) { free(dma->desc[bux_idx]); } + if(dma->buf && dma->buf[bux_idx]) { free(dma->buf[bux_idx]); } } + if(dma->buf) { free(dma->buf); } + if(dma->desc) { free(dma->desc); } vQueueDelete(dma->queue); vSemaphoreDelete(dma->mux); free(dma); return ESP_OK; } -static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len) -{ +static i2s_dma_t* i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len) { int bux_idx; int sample_size = p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num; - i2s_dma_t *dma = (i2s_dma_t*) malloc(sizeof(i2s_dma_t)); - if (dma == NULL) { + i2s_dma_t* dma = (i2s_dma_t*)malloc(sizeof(i2s_dma_t)); + if(dma == NULL) { ESP_LOGE(I2S_TAG, "Error malloc i2s_dma_t"); return NULL; } memset(dma, 0, sizeof(i2s_dma_t)); - dma->buf = (char **)malloc(sizeof(char*) * dma_buf_count); - if (dma->buf == NULL) { + dma->buf = (char**)malloc(sizeof(char*) * dma_buf_count); + if(dma->buf == NULL) { ESP_LOGE(I2S_TAG, "Error malloc dma buffer pointer"); free(dma); return NULL; } memset(dma->buf, 0, sizeof(char*) * dma_buf_count); - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->buf[bux_idx] = (char*) heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_DMA); - if (dma->buf[bux_idx] == NULL) { + for(bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { + dma->buf[bux_idx] = (char*)heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_DMA); + if(dma->buf[bux_idx] == NULL) { ESP_LOGE(I2S_TAG, "Error malloc dma buffer"); i2s_destroy_dma_queue(i2s_num, dma); return NULL; @@ -631,28 +590,28 @@ static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, in ESP_LOGD(I2S_TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]); } - dma->desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * dma_buf_count); - if (dma->desc == NULL) { + dma->desc = (lldesc_t**)malloc(sizeof(lldesc_t*) * dma_buf_count); + if(dma->desc == NULL) { ESP_LOGE(I2S_TAG, "Error malloc dma description"); i2s_destroy_dma_queue(i2s_num, dma); return NULL; } - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->desc[bux_idx] = (lldesc_t*) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); - if (dma->desc[bux_idx] == NULL) { + for(bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { + dma->desc[bux_idx] = (lldesc_t*)heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); + if(dma->desc[bux_idx] == NULL) { ESP_LOGE(I2S_TAG, "Error malloc dma description entry"); i2s_destroy_dma_queue(i2s_num, dma); return NULL; } } - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { + for(bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { dma->desc[bux_idx]->owner = 1; dma->desc[bux_idx]->eof = 1; dma->desc[bux_idx]->sosf = 0; dma->desc[bux_idx]->length = dma_buf_len * sample_size; dma->desc[bux_idx]->size = dma_buf_len * sample_size; - dma->desc[bux_idx]->buf = (uint8_t *) dma->buf[bux_idx]; + dma->desc[bux_idx]->buf = (uint8_t*)dma->buf[bux_idx]; dma->desc[bux_idx]->offset = 0; dma->desc[bux_idx]->empty = (uint32_t)((bux_idx < (dma_buf_count - 1)) ? (dma->desc[bux_idx + 1]) : dma->desc[0]); } @@ -663,8 +622,7 @@ static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, in return dma; } -esp_err_t i2s_start(i2s_port_t i2s_num) -{ +esp_err_t i2s_start(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); //start DMA link I2S_ENTER_CRITICAL(); @@ -672,11 +630,11 @@ esp_err_t i2s_start(i2s_port_t i2s_num) esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle); i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), I2S_INTR_MAX); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { i2s_enable_tx_intr(i2s_num); i2s_hal_start_tx(&(p_i2s_obj[i2s_num]->hal)); } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { i2s_enable_rx_intr(i2s_num); i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal)); } @@ -685,16 +643,15 @@ esp_err_t i2s_start(i2s_port_t i2s_num) return ESP_OK; } -esp_err_t i2s_stop(i2s_port_t i2s_num) -{ +esp_err_t i2s_stop(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_ENTER_CRITICAL(); esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { i2s_hal_stop_tx(&(p_i2s_obj[i2s_num]->hal)); i2s_disable_tx_intr(i2s_num); } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { i2s_hal_stop_rx(&(p_i2s_obj[i2s_num]->hal)); i2s_disable_rx_intr(i2s_num); } @@ -706,10 +663,9 @@ esp_err_t i2s_stop(i2s_port_t i2s_num) } #if SOC_I2S_SUPPORTS_ADC_DAC -esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) -{ +esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) { I2S_CHECK((dac_mode < I2S_DAC_CHANNEL_MAX), "i2s dac mode error", ESP_ERR_INVALID_ARG); - if (dac_mode == I2S_DAC_CHANNEL_DISABLE) { + if(dac_mode == I2S_DAC_CHANNEL_DISABLE) { dac_output_disable(DAC_CHANNEL_1); dac_output_disable(DAC_CHANNEL_2); dac_i2s_disable(); @@ -717,25 +673,23 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) dac_i2s_enable(); } - if (dac_mode & I2S_DAC_CHANNEL_RIGHT_EN) { + if(dac_mode & I2S_DAC_CHANNEL_RIGHT_EN) { //DAC1, right channel dac_output_enable(DAC_CHANNEL_1); } - if (dac_mode & I2S_DAC_CHANNEL_LEFT_EN) { + if(dac_mode & I2S_DAC_CHANNEL_LEFT_EN) { //DAC2, left channel dac_output_enable(DAC_CHANNEL_2); } return ESP_OK; } -static esp_err_t _i2s_adc_mode_recover(void) -{ +static esp_err_t _i2s_adc_mode_recover(void) { I2S_CHECK(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), "i2s ADC recover error, not initialized...", ESP_ERR_INVALID_ARG); return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel); } -esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) -{ +esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) { I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG); // For now, we only support SAR ADC1. _i2s_adc_unit = adc_unit; @@ -744,10 +698,9 @@ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) } #endif -esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) -{ +esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t* pin) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (pin == NULL) { + if(pin == NULL) { #if SOC_I2S_SUPPORTS_ADC_DAC return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); #else @@ -755,19 +708,19 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) #endif } - if (pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) { + if(pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) { ESP_LOGE(I2S_TAG, "bck_io_num error"); return ESP_FAIL; } - if (pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) { + if(pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) { ESP_LOGE(I2S_TAG, "ws_io_num error"); return ESP_FAIL; } - if (pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) { + if(pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) { ESP_LOGE(I2S_TAG, "data_out_num error"); return ESP_FAIL; } - if (pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) { + if(pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) { ESP_LOGE(I2S_TAG, "data_in_num error"); return ESP_FAIL; } @@ -776,12 +729,12 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) //Each IIS hw module has a RX and TX unit. //For TX unit, the output signal index should be I2SnO_xxx_OUT_IDX //For TX unit, the input signal index should be I2SnO_xxx_IN_IDX - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig; ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig; data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig; - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { + } else if(p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { bck_sig = i2s_periph_signal[i2s_num].o_bck_in_sig; ws_sig = i2s_periph_signal[i2s_num].o_ws_in_sig; data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig; @@ -789,12 +742,12 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) } //For RX unit, the output signal index should be I2SnI_xxx_OUT_IDX //For RX unit, the input signal index shuld be I2SnI_xxx_IN_IDX - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { bck_sig = i2s_periph_signal[i2s_num].i_bck_out_sig; ws_sig = i2s_periph_signal[i2s_num].i_ws_out_sig; data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig; - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { + } else if(p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig; ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig; data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig; @@ -802,19 +755,19 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) } //For "full-duplex + slave" mode, we should select RX signal index for ws and bck. //For "full-duplex + master" mode, we should select TX signal index for ws and bck. - if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_SLAVE_MODE_MASK) == I2S_FULL_DUPLEX_SLAVE_MODE_MASK) { + if((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_SLAVE_MODE_MASK) == I2S_FULL_DUPLEX_SLAVE_MODE_MASK) { bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig; ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig; - } else if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_MASTER_MODE_MASK) == I2S_FULL_DUPLEX_MASTER_MODE_MASK) { + } else if((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_MASTER_MODE_MASK) == I2S_FULL_DUPLEX_MASTER_MODE_MASK) { bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig; ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig; } gpio_matrix_out_check(pin->data_out_num, data_out_sig, 0, 0); gpio_matrix_in_check(pin->data_in_num, data_in_sig, 0); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { gpio_matrix_out_check(pin->ws_io_num, ws_sig, 0, 0); gpio_matrix_out_check(pin->bck_io_num, bck_sig, 0, 0); - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { + } else if(p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { gpio_matrix_in_check(pin->ws_io_num, ws_sig, 0); gpio_matrix_in_check(pin->bck_io_num, bck_sig, 0); } @@ -823,24 +776,21 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) return ESP_OK; } -esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) -{ +esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((p_i2s_obj[i2s_num]->bytes_per_sample > 0), "bits_per_sample not set", ESP_ERR_INVALID_ARG); return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } #if SOC_I2S_SUPPORTS_PDM -esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr) -{ +esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); i2s_hal_rx_pdm_cfg(&(p_i2s_obj[i2s_num]->hal), dsr); return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } #endif -static esp_err_t i2s_check_cfg_static(i2s_port_t i2s_num, const i2s_config_t *cfg) -{ +static esp_err_t i2s_check_cfg_static(i2s_port_t i2s_num, const i2s_config_t* cfg) { #if SOC_I2S_SUPPORTS_ADC_DAC //We only check if the I2S number is invalid when set to build in ADC and DAC mode. I2S_CHECK(!((cfg->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S ADC built-in only support on I2S0", ESP_ERR_INVALID_ARG); @@ -853,13 +803,14 @@ static esp_err_t i2s_check_cfg_static(i2s_port_t i2s_num, const i2s_config_t *cf return ESP_OK; #endif - I2S_CHECK(cfg->communication_format && (cfg->communication_format < I2S_COMM_FORMAT_STAND_MAX), "invalid communication formats", ESP_ERR_INVALID_ARG); - I2S_CHECK(!((cfg->communication_format & I2S_COMM_FORMAT_STAND_MSB) && (cfg->communication_format & I2S_COMM_FORMAT_STAND_PCM_LONG)), "multiple communication formats specified", ESP_ERR_INVALID_ARG); + I2S_CHECK( + cfg->communication_format && (cfg->communication_format < I2S_COMM_FORMAT_STAND_MAX), "invalid communication formats", ESP_ERR_INVALID_ARG); + I2S_CHECK(!((cfg->communication_format & I2S_COMM_FORMAT_STAND_MSB) && (cfg->communication_format & I2S_COMM_FORMAT_STAND_PCM_LONG)), + "multiple communication formats specified", ESP_ERR_INVALID_ARG); return ESP_OK; } -static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config) -{ +static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t* i2s_config) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG); I2S_CHECK((i2s_check_cfg_static(i2s_num, i2s_config) == ESP_OK), "param check error", ESP_ERR_INVALID_ARG); @@ -875,9 +826,9 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co #endif // configure I2S data port interface. i2s_hal_config_param(&(p_i2s_obj[i2s_num]->hal), i2s_config); - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) { + if((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) { i2s_hal_enable_sig_loopback(&(p_i2s_obj[i2s_num]->hal)); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { + if(p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { i2s_hal_enable_master_mode(&(p_i2s_obj[i2s_num]->hal)); } else { i2s_hal_enable_slave_mode(&(p_i2s_obj[i2s_num]->hal)); @@ -890,47 +841,41 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co return ESP_OK; } -esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) -{ +esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (p_i2s_obj[i2s_num]->rx && p_i2s_obj[i2s_num]->rx->buf != NULL && p_i2s_obj[i2s_num]->rx->buf_size != 0) { - for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { - memset(p_i2s_obj[i2s_num]->rx->buf[i], 0, p_i2s_obj[i2s_num]->rx->buf_size); - } + if(p_i2s_obj[i2s_num]->rx && p_i2s_obj[i2s_num]->rx->buf != NULL && p_i2s_obj[i2s_num]->rx->buf_size != 0) { + for(int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { memset(p_i2s_obj[i2s_num]->rx->buf[i], 0, p_i2s_obj[i2s_num]->rx->buf_size); } } - if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) { + if(p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) { int bytes_left = 0; bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4; - if (bytes_left) { + if(bytes_left) { size_t zero_bytes = 0, bytes_written; - i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); - } - for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { - memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size); + i2s_write(i2s_num, (void*)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); } + for(int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size); } } return ESP_OK; } -esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue) -{ +esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t* i2s_config, int queue_size, void* i2s_queue) { esp_err_t err; I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((i2s_config != NULL), "I2S configuration must not NULL", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), "I2S buffer length at most 1024 and more than 8", ESP_ERR_INVALID_ARG); - if (p_i2s_obj[i2s_num] == NULL) { - p_i2s_obj[i2s_num] = (i2s_obj_t*) malloc(sizeof(i2s_obj_t)); - if (p_i2s_obj[i2s_num] == NULL) { + I2S_CHECK( + (i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_ERR_INVALID_ARG); + I2S_CHECK( + (i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), "I2S buffer length at most 1024 and more than 8", ESP_ERR_INVALID_ARG); + if(p_i2s_obj[i2s_num] == NULL) { + p_i2s_obj[i2s_num] = (i2s_obj_t*)malloc(sizeof(i2s_obj_t)); + if(p_i2s_obj[i2s_num] == NULL) { ESP_LOGE(I2S_TAG, "Malloc I2S driver error"); return ESP_ERR_NO_MEM; } memset(p_i2s_obj[i2s_num], 0, sizeof(i2s_obj_t)); portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED}; - for (int x = 0; x < I2S_NUM_MAX; x++) { - i2s_spinlock[x] = i2s_spinlock_unlocked[0]; - } + for(int x = 0; x < I2S_NUM_MAX; x++) { i2s_spinlock[x] = i2s_spinlock_unlocked[0]; } //To make sure hardware is enabled before any hardware register operations. periph_module_enable(i2s_periph_signal[i2s_num].module); i2s_hal_init(&(p_i2s_obj[i2s_num]->hal), i2s_num); @@ -946,26 +891,25 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, p_i2s_obj[i2s_num]->channel_num = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1; #ifdef CONFIG_PM_ENABLE - if (i2s_config->use_apll) { - err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock); - } else { - err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock); - } - if (err != ESP_OK) { - free(p_i2s_obj[i2s_num]); - p_i2s_obj[i2s_num] = NULL; - ESP_LOGE(I2S_TAG, "I2S pm lock error"); - return err; - } + if(i2s_config->use_apll) { + err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock); + } else { + err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock); + } + if(err != ESP_OK) { + free(p_i2s_obj[i2s_num]); + p_i2s_obj[i2s_num] = NULL; + ESP_LOGE(I2S_TAG, "I2S pm lock error"); + return err; + } #endif //CONFIG_PM_ENABLE //initial interrupt - err = i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle); - if (err != ESP_OK) { + err = i2s_isr_register( + i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle); + if(err != ESP_OK) { #ifdef CONFIG_PM_ENABLE - if (p_i2s_obj[i2s_num]->pm_lock) { - esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock); - } + if(p_i2s_obj[i2s_num]->pm_lock) { esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock); } #endif free(p_i2s_obj[i2s_num]); p_i2s_obj[i2s_num] = NULL; @@ -974,15 +918,15 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, } i2s_stop(i2s_num); err = i2s_param_config(i2s_num, i2s_config); - if (err != ESP_OK) { + if(err != ESP_OK) { i2s_driver_uninstall(i2s_num); ESP_LOGE(I2S_TAG, "I2S param configure error"); return err; } - if (i2s_queue) { + if(i2s_queue) { p_i2s_obj[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); - *((QueueHandle_t*) i2s_queue) = p_i2s_obj[i2s_num]->i2s_queue; + *((QueueHandle_t*)i2s_queue) = p_i2s_obj[i2s_num]->i2s_queue; ESP_LOGI(I2S_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_i2s_obj[i2s_num]->i2s_queue)); } else { p_i2s_obj[i2s_num]->i2s_queue = NULL; @@ -995,26 +939,25 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, return ESP_OK; } -esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) -{ +esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (p_i2s_obj[i2s_num] == NULL) { + if(p_i2s_obj[i2s_num] == NULL) { ESP_LOGI(I2S_TAG, "already uninstalled"); return ESP_OK; } i2s_stop(i2s_num); esp_intr_free(p_i2s_obj[i2s_num]->i2s_isr_handle); - if (p_i2s_obj[i2s_num]->tx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + if(p_i2s_obj[i2s_num]->tx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->tx); p_i2s_obj[i2s_num]->tx = NULL; } - if (p_i2s_obj[i2s_num]->rx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + if(p_i2s_obj[i2s_num]->rx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->rx); p_i2s_obj[i2s_num]->rx = NULL; } - if (p_i2s_obj[i2s_num]->i2s_queue) { + if(p_i2s_obj[i2s_num]->i2s_queue) { vQueueDelete(p_i2s_obj[i2s_num]->i2s_queue); p_i2s_obj[i2s_num]->i2s_queue = NULL; } @@ -1025,9 +968,7 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) rtc_clk_apll_enable(0, 0, 0, 0, 0); } #ifdef CONFIG_PM_ENABLE - if (p_i2s_obj[i2s_num]->pm_lock) { - esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock); - } + if(p_i2s_obj[i2s_num]->pm_lock) { esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock); } #endif free(p_i2s_obj[i2s_num]); @@ -1037,8 +978,7 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) return ESP_OK; } -esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait) -{ +esp_err_t i2s_write(i2s_port_t i2s_num, const void* src, size_t size, size_t* bytes_written, TickType_t ticks_to_wait) { char *data_ptr, *src_byte; size_t bytes_can_write; *bytes_written = 0; @@ -1049,21 +989,18 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock); #endif - src_byte = (char *)src; - while (size > 0) { - if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { - break; - } + src_byte = (char*)src; + while(size > 0) { + if(p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { + if(xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { break; } p_i2s_obj[i2s_num]->tx->rw_pos = 0; } - ESP_LOGD(I2S_TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr); + ESP_LOGD(I2S_TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, + (int)p_i2s_obj[i2s_num]->tx->curr_ptr); data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr; data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos; bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos; - if (bytes_can_write > size) { - bytes_can_write = size; - } + if(bytes_can_write > size) { bytes_can_write = size; } memcpy(data_ptr, src_byte, bytes_can_write); size -= bytes_can_write; src_byte += bytes_can_write; @@ -1079,8 +1016,7 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by } #if SOC_I2S_SUPPORTS_ADC_DAC -esp_err_t i2s_adc_enable(i2s_port_t i2s_num) -{ +esp_err_t i2s_adc_enable(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE); I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE); @@ -1092,8 +1028,7 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num) return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } -esp_err_t i2s_adc_disable(i2s_port_t i2s_num) -{ +esp_err_t i2s_adc_disable(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE); I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE); @@ -1104,9 +1039,9 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) } #endif -esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait) -{ - char *data_ptr; +esp_err_t i2s_write_expand( + i2s_port_t i2s_num, const void* src, size_t size, size_t src_bits, size_t aim_bits, size_t* bytes_written, TickType_t ticks_to_wait) { + char* data_ptr; int bytes_can_write, tail; int src_bytes, aim_bytes, zero_bytes; *bytes_written = 0; @@ -1115,20 +1050,20 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz I2S_CHECK((aim_bits * size < SOC_I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); I2S_CHECK((aim_bits >= src_bits), "aim_bits mustn't be less than src_bits", ESP_ERR_INVALID_ARG); I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); - if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { - ESP_LOGE(I2S_TAG,"bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); + if(src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { + ESP_LOGE(I2S_TAG, "bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; } - if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) { - ESP_LOGE(I2S_TAG,"bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); + if(src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) { + ESP_LOGE(I2S_TAG, "bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; } - if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) { - ESP_LOGE(I2S_TAG,"size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size); + if((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) { + ESP_LOGE(I2S_TAG, "size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size); return ESP_ERR_INVALID_ARG; } - if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) { - ESP_LOGE(I2S_TAG,"size must be a multiple of 3 while src_bits is 24, size %d", size); + if(src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) { + ESP_LOGE(I2S_TAG, "size must be a multiple of 3 while src_bits is 24, size %d", size); return ESP_ERR_INVALID_ARG; } @@ -1137,27 +1072,23 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz zero_bytes = aim_bytes - src_bytes; xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); size = size * aim_bytes / src_bytes; - ESP_LOGD(I2S_TAG,"aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size); - while (size > 0) { - if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { - break; - } + ESP_LOGD(I2S_TAG, "aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size); + while(size > 0) { + if(p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { + if(xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { break; } p_i2s_obj[i2s_num]->tx->rw_pos = 0; } data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr; data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos; bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos; - if (bytes_can_write > (int)size) { - bytes_can_write = size; - } + if(bytes_can_write > (int)size) { bytes_can_write = size; } tail = bytes_can_write % aim_bytes; bytes_can_write = bytes_can_write - tail; memset(data_ptr, 0, bytes_can_write); - for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) { + for(int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) { j += zero_bytes; - memcpy(&data_ptr[j], (const char *)(src + *bytes_written), aim_bytes - zero_bytes); + memcpy(&data_ptr[j], (const char*)(src + *bytes_written), aim_bytes - zero_bytes); (*bytes_written) += (aim_bytes - zero_bytes); } size -= bytes_can_write; @@ -1167,12 +1098,11 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz return ESP_OK; } -esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait) -{ +esp_err_t i2s_read(i2s_port_t i2s_num, void* dest, size_t size, size_t* bytes_read, TickType_t ticks_to_wait) { char *data_ptr, *dest_byte; int bytes_can_read; *bytes_read = 0; - dest_byte = (char *)dest; + dest_byte = (char*)dest; I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((size < SOC_I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG); @@ -1180,19 +1110,15 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock); #endif - while (size > 0) { - if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { - break; - } + while(size > 0) { + if(p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { + if(xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { break; } p_i2s_obj[i2s_num]->rx->rw_pos = 0; } data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr; data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos; bytes_can_read = p_i2s_obj[i2s_num]->rx->buf_size - p_i2s_obj[i2s_num]->rx->rw_pos; - if (bytes_can_read > (int)size) { - bytes_can_read = size; - } + if(bytes_can_read > (int)size) { bytes_can_read = size; } memcpy(dest_byte, data_ptr, bytes_can_read); size -= bytes_can_read; dest_byte += bytes_can_read; diff --git a/components/audio/inc/esp_equalizer.h b/components/audio/inc/esp_equalizer.h index e1f815d1..dbb0f74f 100644 --- a/components/audio/inc/esp_equalizer.h +++ b/components/audio/inc/esp_equalizer.h @@ -5,8 +5,7 @@ #define _ESP_EQUALIZER_H #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif /** @@ -19,14 +18,14 @@ extern "C" * * @return The equalizer handle. */ -void *esp_equalizer_init(int nch, int g_rate, int n_band, int use_xmms_original_freqs); +void* esp_equalizer_init(int nch, int g_rate, int n_band, int use_xmms_original_freqs); /** * @brief Uninitialize the equalizer handle. * * @param handle The the equalizer handle */ -void esp_equalizer_uninit(void *handle); +void esp_equalizer_uninit(void* handle); /** * @brief Process the data through the equalizer @@ -39,7 +38,7 @@ void esp_equalizer_uninit(void *handle); * * @return Length of pcm_buf after processing */ -int esp_equalizer_process(void *handle, unsigned char *pcm_buf, int length, int g_rate, int nch); +int esp_equalizer_process(void* handle, unsigned char* pcm_buf, int length, int g_rate, int nch); /** * @brief Set the number of sub-bands for the equalizer @@ -49,7 +48,7 @@ int esp_equalizer_process(void *handle, unsigned char *pcm_buf, int length, int * @param index The index of audio sub-bands. e.g. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. * @param nch The audio channel number */ -void esp_equalizer_set_band_value(void *handle, float value, int index, int nch); +void esp_equalizer_set_band_value(void* handle, float value, int index, int nch); /** * @brief Get the number of the equalizer sub-bands @@ -58,7 +57,7 @@ void esp_equalizer_set_band_value(void *handle, float value, int index, int nch) * * @return The number of the equalizer sub-bands */ -int esp_equalizer_get_band_count(void *handle); +int esp_equalizer_get_band_count(void* handle); /** * @brief Get the value of the equalizer sub-bands @@ -69,7 +68,7 @@ int esp_equalizer_get_band_count(void *handle); * * @return The number of the equalizer sub-bands */ -float esp_equalizer_get_band_value(void *handle, int index, int nch); +float esp_equalizer_get_band_value(void* handle, int index, int nch); #ifdef __cplusplus } diff --git a/components/audio/link_helper.c b/components/audio/link_helper.c index 1a3df177..078d4734 100644 --- a/components/audio/link_helper.c +++ b/components/audio/link_helper.c @@ -1,3 +1 @@ -void dummy_obj() { - return; -} +void dummy_obj() { return; } diff --git a/components/display/ILI9341.c b/components/display/ILI9341.c index f6a2dc30..1ab8c333 100644 --- a/components/display/ILI9341.c +++ b/components/display/ILI9341.c @@ -19,329 +19,364 @@ #define SHADOW_BUFFER #define USE_IRAM -#define PAGE_BLOCK 2048 -#define ENABLE_WRITE 0x2c -#define MADCTL_MX 0x40 -#define TFT_RGB_BGR 0x08 +#define PAGE_BLOCK 2048 +#define ENABLE_WRITE 0x2c +#define MADCTL_MX 0x40 +#define TFT_RGB_BGR 0x08 -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) static char TAG[] = "ILI9341"; -enum { ILI9341, ILI9341_24 }; //ILI9341_24 for future use... +enum { ILI9341, ILI9341_24 }; //ILI9341_24 for future use... struct PrivateSpace { - uint8_t *iRAM, *Shadowbuffer; - struct { - uint16_t Height, Width; - } Offset; - uint8_t MADCtl, PageSize; - uint8_t Model; + uint8_t *iRAM, *Shadowbuffer; + struct { + uint16_t Height, Width; + } Offset; + uint8_t MADCtl, PageSize; + uint8_t Model; }; // Functions are not declared to minimize # of lines -static void WriteByte( struct GDS_Device* Device, uint8_t Data ) { - Device->WriteData( Device, &Data, 1 ); +static void WriteByte(struct GDS_Device* Device, uint8_t Data) { Device->WriteData(Device, &Data, 1); } + +static void SetColumnAddress(struct GDS_Device* Device, uint16_t Start, uint16_t End) { + uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); + Device->WriteCommand(Device, 0x2A); + Device->WriteData(Device, (uint8_t*)&Addr, 4); } -static void SetColumnAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) { - uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); - Device->WriteCommand( Device, 0x2A ); - Device->WriteData( Device, (uint8_t*) &Addr, 4 ); +static void SetRowAddress(struct GDS_Device* Device, uint16_t Start, uint16_t End) { + uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); + Device->WriteCommand(Device, 0x2B); + Device->WriteData(Device, (uint8_t*)&Addr, 4); } -static void SetRowAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) { - uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); - Device->WriteCommand( Device, 0x2B ); - Device->WriteData( Device, (uint8_t*) &Addr, 4 ); -} +static void Update16(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; -static void Update16( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - #ifdef SHADOW_BUFFER - uint32_t *optr = (uint32_t*) Private->Shadowbuffer, *iptr = (uint32_t*) Device->Framebuffer; - int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - - for (int r = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width is always a multiple of 2) - for (int c = 0; c < Device->Width / 2; c++, iptr++, optr++) { - if (*optr != *iptr) { - *optr = *iptr; - if (c < FirstCol) FirstCol = c; - if (c > LastCol) LastCol = c; - if (FirstRow < 0) FirstRow = r; - LastRow = r; - } - } + uint32_t *optr = (uint32_t*)Private->Shadowbuffer, *iptr = (uint32_t*)Device->Framebuffer; + int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - // wait for a large enough window - careful that window size might increase by more than a line at once ! - if (FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; - - FirstCol *= 2; - LastCol = LastCol * 2 + 1; - SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); - SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width ); - Device->WriteCommand( Device, ENABLE_WRITE ); - - int ChunkSize = (LastCol - FirstCol + 1) * 2; - - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - uint8_t *optr = Private->iRAM; - for (int i = FirstRow; i <= LastRow; i++) { - memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); - optr += ChunkSize; - if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; - Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); - optr = Private->iRAM; - } - } else for (int i = FirstRow; i <= LastRow; i++) { - Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize ); - } + for(int r = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width is always a multiple of 2) + for(int c = 0; c < Device->Width / 2; c++, iptr++, optr++) { + if(*optr != *iptr) { + *optr = *iptr; + if(c < FirstCol) FirstCol = c; + if(c > LastCol) LastCol = c; + if(FirstRow < 0) FirstRow = r; + LastRow = r; + } + } - FirstCol = Device->Width / 2; LastCol = 0; - FirstRow = -1; - } + // wait for a large enough window - careful that window size might increase by more than a line at once ! + if(FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; + + FirstCol *= 2; + LastCol = LastCol * 2 + 1; + SetRowAddress(Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); + SetColumnAddress(Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width); + Device->WriteCommand(Device, ENABLE_WRITE); + + int ChunkSize = (LastCol - FirstCol + 1) * 2; + + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + uint8_t* optr = Private->iRAM; + for(int i = FirstRow; i <= LastRow; i++) { + memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); + optr += ChunkSize; + if(optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; + Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); + optr = Private->iRAM; + } + } else + for(int i = FirstRow; i <= LastRow; i++) { + Device->WriteData(Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); + } + + FirstCol = Device->Width / 2; + LastCol = 0; + FirstRow = -1; + } #else - // always update by full lines - SetColumnAddress( Device, Private->Offset.Width, Device->Width - 1); - - for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { - int Height = min(Private->PageSize, Device->Height - r); - - SetRowAddress( Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1 ); - Device->WriteCommand(Device, ENABLE_WRITE); - - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 ); - Device->WriteData( Device, Private->iRAM, Height * Device->Width * 2 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 ); - } - } -#endif + // always update by full lines + SetColumnAddress(Device, Private->Offset.Width, Device->Width - 1); + + for(int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { + int Height = min(Private->PageSize, Device->Height - r); + + SetRowAddress(Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1); + Device->WriteCommand(Device, ENABLE_WRITE); + + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2); + Device->WriteData(Device, Private->iRAM, Height * Device->Width * 2); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2); + } + } +#endif } -static void Update24( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - +static void Update24(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + #ifdef SHADOW_BUFFER - uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer; - int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0; + uint16_t *optr = (uint16_t*)Private->Shadowbuffer, *iptr = (uint16_t*)Device->Framebuffer; + int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - for (int r = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width always / by 2) - for (int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) { - if (*optr != *iptr) { - *optr = *iptr; - if (c < FirstCol) FirstCol = c; - if (c > LastCol) LastCol = c; - if (FirstRow < 0) FirstRow = r; - LastRow = r; - } - } + for(int r = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width always / by 2) + for(int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) { + if(*optr != *iptr) { + *optr = *iptr; + if(c < FirstCol) FirstCol = c; + if(c > LastCol) LastCol = c; + if(FirstRow < 0) FirstRow = r; + LastRow = r; + } + } - // do we have enough to send (cols are divided by 3/2) - if (FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2 ) / 3) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; - - FirstCol = (FirstCol * 2) / 3; - LastCol = (LastCol * 2 + 1 ) / 3; - SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); - SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width ); - Device->WriteCommand( Device, ENABLE_WRITE ); - - int ChunkSize = (LastCol - FirstCol + 1) * 3; - - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - uint8_t *optr = Private->iRAM; - for (int i = FirstRow; i <= LastRow; i++) { - memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); - optr += ChunkSize; - if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; - Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); - optr = Private->iRAM; - } - } else for (int i = FirstRow; i <= LastRow; i++) { - Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize ); - } + // do we have enough to send (cols are divided by 3/2) + if(FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2) / 3) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; - FirstCol = (Device->Width * 3) / 2; LastCol = 0; - FirstRow = -1; - } + FirstCol = (FirstCol * 2) / 3; + LastCol = (LastCol * 2 + 1) / 3; + SetRowAddress(Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); + SetColumnAddress(Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width); + Device->WriteCommand(Device, ENABLE_WRITE); + + int ChunkSize = (LastCol - FirstCol + 1) * 3; + + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + uint8_t* optr = Private->iRAM; + for(int i = FirstRow; i <= LastRow; i++) { + memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); + optr += ChunkSize; + if(optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; + Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); + optr = Private->iRAM; + } + } else + for(int i = FirstRow; i <= LastRow; i++) { + Device->WriteData(Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); + } + + FirstCol = (Device->Width * 3) / 2; + LastCol = 0; + FirstRow = -1; + } #else - // always update by full lines - SetColumnAddress( Device, Private->Offset.Width, Device->Width - 1); - - for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { - int Height = min(Private->PageSize, Device->Height - r); - - SetRowAddress( Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1 ); - Device->WriteCommand(Device, ENABLE_WRITE); - - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 ); - Device->WriteData( Device, Private->iRAM, Height * Device->Width * 3 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 ); - } - } -#endif + // always update by full lines + SetColumnAddress(Device, Private->Offset.Width, Device->Width - 1); + + for(int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { + int Height = min(Private->PageSize, Device->Height - r); + + SetRowAddress(Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1); + Device->WriteCommand(Device, ENABLE_WRITE); + + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3); + Device->WriteData(Device, Private->iRAM, Height * Device->Width * 3); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3); + } + } +#endif } -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - ESP_LOGI(TAG, "SetLayout 197 HFlip=%d VFlip=%d Rotate=%d (1=true)", Layout->HFlip, Layout->VFlip, Layout->Rotate); - // D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX - //Command 0 1 ↑ XX 0 0 1 1 0 1 1 0 36h - //Parameter 1 1 ↑ XX MY MX MV ML BGR MH 0 0 00 - //Orientation 0: MADCtl = 0x80 = 1000 0000 (MY=1) - if ((Device->Height)>(Device->Width)){ //Resolution = 320x240 - Private->MADCtl = (1 << 7); // 0x80 = default (no Rotation an no Flip) - if (Layout->HFlip) { //Flip Horizontal - int a = Private->MADCtl; - Private->MADCtl = (a ^ (1 << 7)); - } - if (Layout->Rotate) { //Rotate 180 degr. - int a = Private->MADCtl; - a = (a ^ (1 << 7)); - Private->MADCtl = (a ^ (1 << 6)); - } - if (Layout->VFlip) { //Flip Vertical - int a = Private->MADCtl; - Private->MADCtl = (a ^ (1 << 6)); - } - } else { //Resolution = 240x320 - Private->MADCtl = (1 << 5); // 0x20 = default (no Rotation an no Flip) - if (Layout->HFlip) { //Flip Horizontal - int a = Private->MADCtl; - Private->MADCtl = (a ^ (1 << 6)); - } - if (Layout->Rotate) { //Rotate 180 degr. - int a = Private->MADCtl; - a = (a ^ (1 << 7)); - Private->MADCtl = (a ^ (1 << 6)); - } - if (Layout->VFlip) { //Flip Vertical - int a = Private->MADCtl; - Private->MADCtl = (a ^ (1 << 7)); - } - } - - Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl | (1 << 3)) : (Private->MADCtl & ~(1 << 3)); +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + ESP_LOGI(TAG, "SetLayout 197 HFlip=%d VFlip=%d Rotate=%d (1=true)", Layout->HFlip, Layout->VFlip, Layout->Rotate); + // D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX + //Command 0 1 ↑ XX 0 0 1 1 0 1 1 0 36h + //Parameter 1 1 ↑ XX MY MX MV ML BGR MH 0 0 00 + //Orientation 0: MADCtl = 0x80 = 1000 0000 (MY=1) + if((Device->Height) > (Device->Width)) { //Resolution = 320x240 + Private->MADCtl = (1 << 7); // 0x80 = default (no Rotation an no Flip) + if(Layout->HFlip) { //Flip Horizontal + int a = Private->MADCtl; + Private->MADCtl = (a ^ (1 << 7)); + } + if(Layout->Rotate) { //Rotate 180 degr. + int a = Private->MADCtl; + a = (a ^ (1 << 7)); + Private->MADCtl = (a ^ (1 << 6)); + } + if(Layout->VFlip) { //Flip Vertical + int a = Private->MADCtl; + Private->MADCtl = (a ^ (1 << 6)); + } + } else { //Resolution = 240x320 + Private->MADCtl = (1 << 5); // 0x20 = default (no Rotation an no Flip) + if(Layout->HFlip) { //Flip Horizontal + int a = Private->MADCtl; + Private->MADCtl = (a ^ (1 << 6)); + } + if(Layout->Rotate) { //Rotate 180 degr. + int a = Private->MADCtl; + a = (a ^ (1 << 7)); + Private->MADCtl = (a ^ (1 << 6)); + } + if(Layout->VFlip) { //Flip Vertical + int a = Private->MADCtl; + Private->MADCtl = (a ^ (1 << 7)); + } + } - ESP_LOGI(TAG, "SetLayout 255 Private->MADCtl=%hhu", Private->MADCtl); + Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl | (1 << 3)) : (Private->MADCtl & ~(1 << 3)); - Device->WriteCommand( Device, 0x36 ); - WriteByte( Device, Private->MADCtl ); - - Device->WriteCommand( Device, Layout->Invert ? 0x21 : 0x20 ); - + ESP_LOGI(TAG, "SetLayout 255 Private->MADCtl=%hhu", Private->MADCtl); + + Device->WriteCommand(Device, 0x36); + WriteByte(Device, Private->MADCtl); + + Device->WriteCommand(Device, Layout->Invert ? 0x21 : 0x20); #ifdef SHADOW_BUFFER - // force a full refresh (almost ...) - memset(Private->Shadowbuffer, 0xAA, Device->FramebufferSize); -#endif -} - -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0x29 ); } //DISPON =0x29 -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0x28 ); } //DISPOFF=0x28 - -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0x51 ); - WriteByte( Device, Contrast ); - - Device->SetContrast = NULL; - GDS_SetContrast( Device, Contrast ); - Device->SetContrast = SetContrast; // 0x00 value means the lowest brightness and 0xFF value means the highest brightness. + // force a full refresh (almost ...) + memset(Private->Shadowbuffer, 0xAA, Device->FramebufferSize); +#endif } -static bool Init( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - int Depth = (Device->Depth + 8 - 1) / 8; - - Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth)); +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0x29); } //DISPON =0x29 +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0x28); } //DISPOFF=0x28 -#ifdef SHADOW_BUFFER - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0x51); + WriteByte(Device, Contrast); + + Device->SetContrast = NULL; + GDS_SetContrast(Device, Contrast); + Device->SetContrast = SetContrast; // 0x00 value means the lowest brightness and 0xFF value means the highest brightness. +} + +static bool Init(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + int Depth = (Device->Depth + 8 - 1) / 8; + + Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth)); + +#ifdef SHADOW_BUFFER + Private->Shadowbuffer = malloc(Device->FramebufferSize); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); #endif #ifdef USE_IRAM - Private->iRAM = heap_caps_malloc( (Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); + Private->iRAM = heap_caps_malloc((Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); #endif - ESP_LOGI(TAG, "ILI9341 with bit default-depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM); - - // Sleepout + Booster - Device->WriteCommand( Device, 0x11 ); - - // set flip modes & contrast - GDS_SetContrast( Device, 0x7f ); - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - - // set screen depth (16/18) *** INTERFACE PIXEL FORMAT: 0x66=18 bit; 0x55=16 bit - Device->WriteCommand( Device, 0x3A ); - if (Private->Model == ILI9341_24) WriteByte( Device, Device->Depth == 24 ? 0x66 : 0x55 ); - else WriteByte( Device, Device->Depth == 24 ? 0x66 : 0x55 ); + ESP_LOGI(TAG, "ILI9341 with bit default-depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM); - ESP_LOGI(TAG, "ILI9341_Init 312 device-depth %u, 0x66/0x55=0x%X", Device->Depth, Device->Depth == 24 ? 0x66 : 0x55); + // Sleepout + Booster + Device->WriteCommand(Device, 0x11); - // no Display Inversion (INVOFF=0x20 INVON=0x21) - Device->WriteCommand( Device, 0x20 ); + // set flip modes & contrast + GDS_SetContrast(Device, 0x7f); + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); - //Gamma Correction: Enable next two line and enabel one of the Test0x Section... or build you own 15 Parameter... - Device->WriteCommand( Device, 0xF2 ); WriteByte( Device, 0x03 ); // 3Gamma Function: Disable = default (0x02), Enable (0x03) - Device->WriteCommand( Device, 0x26 ); WriteByte( Device, 0x01 ); // Gamma curve selected (0x01, 0x02, 0x04, 0x08) - A maximum of 4 fixed gamma curves can be selected - //Gamma Correction Test01 - Device->WriteCommand( Device, 0xE0 ); // Positive Gamma Correction (15 Parameter) - WriteByte( Device, 0x0F ); WriteByte( Device, 0x31 ); WriteByte( Device, 0x2B ); WriteByte( Device, 0x0C ); WriteByte( Device, 0x0E ); - WriteByte( Device, 0x08 ); WriteByte( Device, 0x4E ); WriteByte( Device, 0xF1 ); WriteByte( Device, 0x37 ); WriteByte( Device, 0x07 ); - WriteByte( Device, 0x10 ); WriteByte( Device, 0x03 ); WriteByte( Device, 0x0E ); WriteByte( Device, 0x09 ); WriteByte( Device, 0x00 ); - Device->WriteCommand( Device, 0xE1 ); // Negative Gamma Correction (15 Parameter) - WriteByte( Device, 0x00 ); WriteByte( Device, 0x0E ); WriteByte( Device, 0x14 ); WriteByte( Device, 0x03 ); WriteByte( Device, 0x11 ); - WriteByte( Device, 0x07 ); WriteByte( Device, 0x31 ); WriteByte( Device, 0xC1 ); WriteByte( Device, 0x48 ); WriteByte( Device, 0x08 ); - WriteByte( Device, 0x0F ); WriteByte( Device, 0x0C ); WriteByte( Device, 0x31 ); WriteByte( Device, 0x36 ); WriteByte( Device, 0x0F ); - - // gone with the wind - Device->DisplayOn( Device ); - Device->Update( Device ); + // set screen depth (16/18) *** INTERFACE PIXEL FORMAT: 0x66=18 bit; 0x55=16 bit + Device->WriteCommand(Device, 0x3A); + if(Private->Model == ILI9341_24) + WriteByte(Device, Device->Depth == 24 ? 0x66 : 0x55); + else + WriteByte(Device, Device->Depth == 24 ? 0x66 : 0x55); - return true; -} + ESP_LOGI(TAG, "ILI9341_Init 312 device-depth %u, 0x66/0x55=0x%X", Device->Depth, Device->Depth == 24 ? 0x66 : 0x55); + + // no Display Inversion (INVOFF=0x20 INVON=0x21) + Device->WriteCommand(Device, 0x20); + + //Gamma Correction: Enable next two line and enabel one of the Test0x Section... or build you own 15 Parameter... + Device->WriteCommand(Device, 0xF2); + WriteByte(Device, 0x03); // 3Gamma Function: Disable = default (0x02), Enable (0x03) + Device->WriteCommand(Device, 0x26); + WriteByte(Device, 0x01); // Gamma curve selected (0x01, 0x02, 0x04, 0x08) - A maximum of 4 fixed gamma curves can be selected + //Gamma Correction Test01 + Device->WriteCommand(Device, 0xE0); // Positive Gamma Correction (15 Parameter) + WriteByte(Device, 0x0F); + WriteByte(Device, 0x31); + WriteByte(Device, 0x2B); + WriteByte(Device, 0x0C); + WriteByte(Device, 0x0E); + WriteByte(Device, 0x08); + WriteByte(Device, 0x4E); + WriteByte(Device, 0xF1); + WriteByte(Device, 0x37); + WriteByte(Device, 0x07); + WriteByte(Device, 0x10); + WriteByte(Device, 0x03); + WriteByte(Device, 0x0E); + WriteByte(Device, 0x09); + WriteByte(Device, 0x00); + Device->WriteCommand(Device, 0xE1); // Negative Gamma Correction (15 Parameter) + WriteByte(Device, 0x00); + WriteByte(Device, 0x0E); + WriteByte(Device, 0x14); + WriteByte(Device, 0x03); + WriteByte(Device, 0x11); + WriteByte(Device, 0x07); + WriteByte(Device, 0x31); + WriteByte(Device, 0xC1); + WriteByte(Device, 0x48); + WriteByte(Device, 0x08); + WriteByte(Device, 0x0F); + WriteByte(Device, 0x0C); + WriteByte(Device, 0x31); + WriteByte(Device, 0x36); + WriteByte(Device, 0x0F); + + // gone with the wind + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} static const struct GDS_Device ILI9341_X = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, - .SetLayout = SetLayout, - .Update = Update16, .Init = Init, - .Mode = GDS_RGB565, .Depth = 16, -}; + .DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetLayout = SetLayout, + .Update = Update16, + .Init = Init, + .Mode = GDS_RGB565, + .Depth = 16, +}; -struct GDS_Device* ILI9341_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - uint8_t Model; - int Depth=16; // 16bit colordepth - - if(Driver->common.driver == sys_display_drivers_ILI9341) Model = ILI9341; - else if(Driver->common.driver == sys_display_drivers_ILI9341_24) Model = ILI9341_24; - else return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - - *Device = ILI9341_X; - Depth = Driver->common.bitDepth != 0?Driver->common.bitDepth:Depth; - struct PrivateSpace* Private = (struct PrivateSpace*) Device->Private; - Private->Model = Model; - ESP_LOGI(TAG, "ILI9341_Detect 391 Driver= %s Depth=%d", Model==ILI9341?"ILI9341":"ILI9341_24", Depth); +struct GDS_Device* ILI9341_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + uint8_t Model; + int Depth = 16; // 16bit colordepth - if (Depth == 18) { - Device->Mode = GDS_RGB888; - Device->Depth = 24; - Device->Update = Update24; - } - - if (Model == ILI9341_24) Device->SetContrast = SetContrast; + if(Driver->common.driver == sys_display_drivers_ILI9341) + Model = ILI9341; + else if(Driver->common.driver == sys_display_drivers_ILI9341_24) + Model = ILI9341_24; + else + return NULL; - return Device; + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); + + *Device = ILI9341_X; + Depth = Driver->common.bitDepth != 0 ? Driver->common.bitDepth : Depth; + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + Private->Model = Model; + ESP_LOGI(TAG, "ILI9341_Detect 391 Driver= %s Depth=%d", Model == ILI9341 ? "ILI9341" : "ILI9341_24", Depth); + + if(Depth == 18) { + Device->Mode = GDS_RGB888; + Device->Depth = 24; + Device->Update = Update24; + } + + if(Model == ILI9341_24) Device->SetContrast = SetContrast; + + return Device; } \ No newline at end of file diff --git a/components/display/SH1106.c b/components/display/SH1106.c index 7a2f0300..37ae6520 100644 --- a/components/display/SH1106.c +++ b/components/display/SH1106.c @@ -22,144 +22,144 @@ static char TAG[] = "SH1106"; struct PrivateSpace { - uint8_t *Shadowbuffer; + uint8_t* Shadowbuffer; }; // Functions are not declared to minimize # of lines -static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - // well, unfortunately this driver is 132 colums but most displays are 128... - if (Device->Width != 132) Start += 2; - Device->WriteCommand( Device, 0x10 | (Start >> 4) ); - Device->WriteCommand( Device, 0x00 | (Start & 0x0f) ); +static void SetColumnAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + // well, unfortunately this driver is 132 colums but most displays are 128... + if(Device->Width != 132) Start += 2; + Device->WriteCommand(Device, 0x10 | (Start >> 4)); + Device->WriteCommand(Device, 0x00 | (Start & 0x0f)); } -static void SetPageAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0xB0 | Start ); -} +static void SetPageAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { Device->WriteCommand(Device, 0xB0 | Start); } -static void Update( struct GDS_Device* Device ) { +static void Update(struct GDS_Device* Device) { #ifdef SHADOW_BUFFER - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - // not sure the compiler does not have to redo all calculation in for loops, so local it is - int width = Device->Width, rows = Device->Height / 8; - uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer; - - // by row, find first and last columns that have been updated - for (int r = 0; r < rows; r++) { - uint8_t first = 0, last; - for (int c = 0; c < width; c++) { - if (*iptr != *optr) { - if (!first) first = c + 1; - last = c ; - } - *optr++ = *iptr++; - } - - // now update the display by "byte rows" - if (first--) { - SetColumnAddress( Device, first, last ); - SetPageAddress( Device, r, r); - Device->WriteData( Device, Private->Shadowbuffer + r*width + first, last - first + 1); - } - } -#else - // SH1106 requires a page-by-page update and has no end Page/Column - for (int i = 0; i < Device->Height / 8 ; i++) { - SH1106_SetPageAddress( Device, i, 0); - SH1106_SetColumnAddress( Device, 0, 0); - SH1106_WriteData( Device, Device->Framebuffer + i*Device->Width, Device->Width ); - } -#endif -} + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + // not sure the compiler does not have to redo all calculation in for loops, so local it is + int width = Device->Width, rows = Device->Height / 8; + uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer; -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - Device->WriteCommand( Device, Layout->HFlip ? 0xA1 : 0xA0 ); - Device->WriteCommand( Device, Layout->VFlip ? 0xC8 : 0xC0 ); - Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 ); -} + // by row, find first and last columns that have been updated + for(int r = 0; r < rows; r++) { + uint8_t first = 0, last; + for(int c = 0; c < width; c++) { + if(*iptr != *optr) { + if(!first) first = c + 1; + last = c; + } + *optr++ = *iptr++; + } -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } - -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0x81 ); - Device->WriteCommand( Device, Contrast ); -} - -static void SPIParams(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post) { - *CS_post = Speed / (8*1000*1000); -} - -static bool Init( struct GDS_Device* Device ) { -#ifdef SHADOW_BUFFER - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; -#ifdef USE_IRAM - if (Device->IF == GDS_IF_SPI) Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); - else + // now update the display by "byte rows" + if(first--) { + SetColumnAddress(Device, first, last); + SetPageAddress(Device, r, r); + Device->WriteData(Device, Private->Shadowbuffer + r * width + first, last - first + 1); + } + } +#else + // SH1106 requires a page-by-page update and has no end Page/Column + for(int i = 0; i < Device->Height / 8; i++) { + SH1106_SetPageAddress(Device, i, 0); + SH1106_SetColumnAddress(Device, 0, 0); + SH1106_WriteData(Device, Device->Framebuffer + i * Device->Width, Device->Width); + } #endif - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - NullCheck( Private->Shadowbuffer, return false ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); -#endif - - // need to be off and disable display RAM - Device->DisplayOff( Device ); - Device->WriteCommand( Device, 0xA5 ); - - // charge pump regulator, do direct init - Device->WriteCommand( Device, 0xAD ); - Device->WriteCommand( Device, 0x8B ); - - // COM pins HW config (alternative:EN) - some display might need something difference - Device->WriteCommand( Device, 0xDA ); - Device->WriteCommand( Device, 1 << 4); - - // MUX Ratio - Device->WriteCommand( Device, 0xA8 ); - Device->WriteCommand( Device, Device->Height - 1); - // Display Offset - Device->WriteCommand( Device, 0xD3 ); - Device->WriteCommand( Device, 0 ); - // Display Start Line - Device->WriteCommand( Device, 0x40 + 0x00 ); - Device->SetContrast( Device, 0x7F ); - // set flip modes - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - // no Display Inversion - Device->WriteCommand( Device, 0xA6 ); - // set Clocks - Device->WriteCommand( Device, 0xD5 ); - Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); - - // gone with the wind - Device->WriteCommand( Device, 0xA4 ); - Device->DisplayOn( Device ); - Device->Update( Device ); - - return true; -} +} -static const struct GDS_Device SH1106 = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, - .SetLayout = SetLayout, - .Update = Update, .Init = Init, - .Depth = 1, - .SPIParams = SPIParams, -#if !defined SHADOW_BUFFER && defined USE_IRAM - .Alloc = GDS_ALLOC_IRAM_SPI; -#endif -}; +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + Device->WriteCommand(Device, Layout->HFlip ? 0xA1 : 0xA0); + Device->WriteCommand(Device, Layout->VFlip ? 0xC8 : 0xC0); + Device->WriteCommand(Device, Layout->Invert ? 0xA7 : 0xA6); +} -struct GDS_Device* SH1106_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - // if (!strcasestr(Driver, "SH1106")) return NULL; - if(Driver->common.driver != sys_display_drivers_SH1106) return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - *Device = SH1106; +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAF); } +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAE); } - ESP_LOGI(TAG, "SH1106 driver"); - - return Device; +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0x81); + Device->WriteCommand(Device, Contrast); +} + +static void SPIParams(int Speed, uint8_t* mode, uint16_t* CS_pre, uint8_t* CS_post) { *CS_post = Speed / (8 * 1000 * 1000); } + +static bool Init(struct GDS_Device* Device) { +#ifdef SHADOW_BUFFER + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; +#ifdef USE_IRAM + if(Device->IF == GDS_IF_SPI) + Private->Shadowbuffer = heap_caps_malloc(Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + else +#endif + Private->Shadowbuffer = malloc(Device->FramebufferSize); + NullCheck(Private->Shadowbuffer, return false); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +#endif + + // need to be off and disable display RAM + Device->DisplayOff(Device); + Device->WriteCommand(Device, 0xA5); + + // charge pump regulator, do direct init + Device->WriteCommand(Device, 0xAD); + Device->WriteCommand(Device, 0x8B); + + // COM pins HW config (alternative:EN) - some display might need something difference + Device->WriteCommand(Device, 0xDA); + Device->WriteCommand(Device, 1 << 4); + + // MUX Ratio + Device->WriteCommand(Device, 0xA8); + Device->WriteCommand(Device, Device->Height - 1); + // Display Offset + Device->WriteCommand(Device, 0xD3); + Device->WriteCommand(Device, 0); + // Display Start Line + Device->WriteCommand(Device, 0x40 + 0x00); + Device->SetContrast(Device, 0x7F); + // set flip modes + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); + // no Display Inversion + Device->WriteCommand(Device, 0xA6); + // set Clocks + Device->WriteCommand(Device, 0xD5); + Device->WriteCommand(Device, (0x08 << 4) | 0x00); + + // gone with the wind + Device->WriteCommand(Device, 0xA4); + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} + +static const struct GDS_Device SH1106 = {.DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetContrast = SetContrast, + .SetLayout = SetLayout, + .Update = Update, + .Init = Init, + .Depth = 1, + .SPIParams = SPIParams, +#if !defined SHADOW_BUFFER && defined USE_IRAM + .Alloc = GDS_ALLOC_IRAM_SPI; +#endif +} +; + +struct GDS_Device* SH1106_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + // if (!strcasestr(Driver, "SH1106")) return NULL; + if(Driver->common.driver != sys_display_drivers_SH1106) return NULL; + + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); + *Device = SH1106; + + ESP_LOGI(TAG, "SH1106 driver"); + + return Device; } \ No newline at end of file diff --git a/components/display/SSD1306.c b/components/display/SSD1306.c index 4f1bb73f..9b6f0e15 100644 --- a/components/display/SSD1306.c +++ b/components/display/SSD1306.c @@ -22,153 +22,158 @@ static char TAG[] = "SSD1306"; struct PrivateSpace { - uint8_t *Shadowbuffer; + uint8_t* Shadowbuffer; }; // Functions are not declared to minimize # of lines -static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x21 ); - Device->WriteCommand( Device, Start ); - Device->WriteCommand( Device, End ); +static void SetColumnAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x21); + Device->WriteCommand(Device, Start); + Device->WriteCommand(Device, End); } -static void SetPageAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x22 ); - Device->WriteCommand( Device, Start ); - Device->WriteCommand( Device, End ); +static void SetPageAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x22); + Device->WriteCommand(Device, Start); + Device->WriteCommand(Device, End); } -static void Update( struct GDS_Device* Device ) { +static void Update(struct GDS_Device* Device) { #ifdef SHADOW_BUFFER - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - // not sure the compiler does not have to redo all calculation in for loops, so local it is - int width = Device->Width, pages = Device->Height / 8; - uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer; - int CurrentPage = -1, FirstCol = -1, LastCol = -1; - - // by row, find first and last columns that have been updated - for (int p = 0; p < pages; p++) { - uint8_t first = 0, last; - for (int c = 0; c < width; c++) { - if (*iptr != *optr) { - if (!first) first = c + 1; - last = c ; - } - *optr++ = *iptr++; - } - - // now update the display by "byte rows" - if (first--) { - // only set column when useful, saves a fair bit of CPU - if (first > FirstCol && first <= FirstCol + 4 && last < LastCol && last >= LastCol - 4) { - first = FirstCol; - last = LastCol; - } else { - SetColumnAddress( Device, first, last ); - FirstCol = first; - LastCol = last; - } - - // Set row only when needed, otherwise let auto-increment work - if (p != CurrentPage) SetPageAddress( Device, p, Device->Height / 8 - 1 ); - CurrentPage = p + 1; - - // actual write - Device->WriteData( Device, Private->Shadowbuffer + p*width + first, last - first + 1); - } - } -#else - // automatic counter and end Page/Column (we assume Height % 8 == 0) - SetColumnAddress( Device, 0, Device->Width - 1); - SetPageAddress( Device, 0, Device->Height / 8 - 1); - Device->WriteData( Device, Device->Framebuffer, Device->FramebufferSize ); -#endif -} + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + // not sure the compiler does not have to redo all calculation in for loops, so local it is + int width = Device->Width, pages = Device->Height / 8; + uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer; + int CurrentPage = -1, FirstCol = -1, LastCol = -1; -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - Device->WriteCommand( Device, Layout->HFlip ? 0xA1 : 0xA0 ); - Device->WriteCommand( Device, Layout->VFlip ? 0xC8 : 0xC0 ); - Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 ); -} - -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } + // by row, find first and last columns that have been updated + for(int p = 0; p < pages; p++) { + uint8_t first = 0, last; + for(int c = 0; c < width; c++) { + if(*iptr != *optr) { + if(!first) first = c + 1; + last = c; + } + *optr++ = *iptr++; + } -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0x81 ); - Device->WriteCommand( Device, Contrast ); -} + // now update the display by "byte rows" + if(first--) { + // only set column when useful, saves a fair bit of CPU + if(first > FirstCol && first <= FirstCol + 4 && last < LastCol && last >= LastCol - 4) { + first = FirstCol; + last = LastCol; + } else { + SetColumnAddress(Device, first, last); + FirstCol = first; + LastCol = last; + } -static bool Init( struct GDS_Device* Device ) { -#ifdef SHADOW_BUFFER - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; -#ifdef USE_IRAM - if (Device->IF == GDS_IF_SPI) Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); - else + // Set row only when needed, otherwise let auto-increment work + if(p != CurrentPage) SetPageAddress(Device, p, Device->Height / 8 - 1); + CurrentPage = p + 1; + + // actual write + Device->WriteData(Device, Private->Shadowbuffer + p * width + first, last - first + 1); + } + } +#else + // automatic counter and end Page/Column (we assume Height % 8 == 0) + SetColumnAddress(Device, 0, Device->Width - 1); + SetPageAddress(Device, 0, Device->Height / 8 - 1); + Device->WriteData(Device, Device->Framebuffer, Device->FramebufferSize); #endif - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - NullCheck( Private->Shadowbuffer, return false ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); -#endif - - // need to be off and disable display RAM - Device->DisplayOff( Device ); - Device->WriteCommand( Device, 0xA5 ); - - // charge pump regulator, do direct init - Device->WriteCommand( Device, 0x8D ); - Device->WriteCommand( Device, 0x14 ); - - // COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something different - Device->WriteCommand( Device, 0xDA ); - Device->WriteCommand( Device, ((Device->Height == 64 ? 1 : 0) << 4) | (0 < 5) ); - - // MUX Ratio - Device->WriteCommand( Device, 0xA8 ); - Device->WriteCommand( Device, Device->Height - 1); - // Display Offset - Device->WriteCommand( Device, 0xD3 ); - Device->WriteCommand( Device, 0 ); - // Display Start Line - Device->WriteCommand( Device, 0x40 + 0x00 ); - Device->SetContrast( Device, 0x7F ); - // set flip modes - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - // no Display Inversion - Device->WriteCommand( Device, 0xA6 ); - // set Clocks - Device->WriteCommand( Device, 0xD5 ); - Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); - // set Adressing Mode Horizontal - Device->WriteCommand( Device, 0x20 ); - Device->WriteCommand( Device, 0 ); - - // gone with the wind - Device->WriteCommand( Device, 0xA4 ); - Device->DisplayOn( Device ); - Device->Update( Device ); - - return true; -} +} + +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + Device->WriteCommand(Device, Layout->HFlip ? 0xA1 : 0xA0); + Device->WriteCommand(Device, Layout->VFlip ? 0xC8 : 0xC0); + Device->WriteCommand(Device, Layout->Invert ? 0xA7 : 0xA6); +} + +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAF); } +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAE); } + +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0x81); + Device->WriteCommand(Device, Contrast); +} + +static bool Init(struct GDS_Device* Device) { +#ifdef SHADOW_BUFFER + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; +#ifdef USE_IRAM + if(Device->IF == GDS_IF_SPI) + Private->Shadowbuffer = heap_caps_malloc(Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + else +#endif + Private->Shadowbuffer = malloc(Device->FramebufferSize); + NullCheck(Private->Shadowbuffer, return false); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +#endif + + // need to be off and disable display RAM + Device->DisplayOff(Device); + Device->WriteCommand(Device, 0xA5); + + // charge pump regulator, do direct init + Device->WriteCommand(Device, 0x8D); + Device->WriteCommand(Device, 0x14); + + // COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something different + Device->WriteCommand(Device, 0xDA); + Device->WriteCommand(Device, ((Device->Height == 64 ? 1 : 0) << 4) | (0 < 5)); + + // MUX Ratio + Device->WriteCommand(Device, 0xA8); + Device->WriteCommand(Device, Device->Height - 1); + // Display Offset + Device->WriteCommand(Device, 0xD3); + Device->WriteCommand(Device, 0); + // Display Start Line + Device->WriteCommand(Device, 0x40 + 0x00); + Device->SetContrast(Device, 0x7F); + // set flip modes + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); + // no Display Inversion + Device->WriteCommand(Device, 0xA6); + // set Clocks + Device->WriteCommand(Device, 0xD5); + Device->WriteCommand(Device, (0x08 << 4) | 0x00); + // set Adressing Mode Horizontal + Device->WriteCommand(Device, 0x20); + Device->WriteCommand(Device, 0); + + // gone with the wind + Device->WriteCommand(Device, 0xA4); + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} static const struct GDS_Device SSD1306 = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, - .SetLayout = SetLayout, - .Update = Update, .Init = Init, - .Mode = GDS_MONO, .Depth = 1, -#if !defined SHADOW_BUFFER && defined USE_IRAM - .Alloc = GDS_ALLOC_IRAM_SPI, -#endif -}; + .DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetContrast = SetContrast, + .SetLayout = SetLayout, + .Update = Update, + .Init = Init, + .Mode = GDS_MONO, + .Depth = 1, +#if !defined SHADOW_BUFFER && defined USE_IRAM + .Alloc = GDS_ALLOC_IRAM_SPI, +#endif +}; -struct GDS_Device* SSD1306_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - if(Driver->common.driver != sys_display_drivers_SSD1306) return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - *Device = SSD1306; - - ESP_LOGI(TAG, "SSD1306 driver"); - - return Device; +struct GDS_Device* SSD1306_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + if(Driver->common.driver != sys_display_drivers_SSD1306) return NULL; + + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); + *Device = SSD1306; + + ESP_LOGI(TAG, "SSD1306 driver"); + + return Device; } \ No newline at end of file diff --git a/components/display/SSD1322.c b/components/display/SSD1322.c index e58f03bf..ada75655 100644 --- a/components/display/SSD1322.c +++ b/components/display/SSD1322.c @@ -17,186 +17,189 @@ #include "gds_private.h" #define SHADOW_BUFFER -#define PAGE_BLOCK 1024 +#define PAGE_BLOCK 1024 -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) static char TAG[] = "SSD1322"; struct PrivateSpace { - uint8_t *iRAM, *Shadowbuffer; - uint8_t ReMap, PageSize; - uint8_t Offset; + uint8_t *iRAM, *Shadowbuffer; + uint8_t ReMap, PageSize; + uint8_t Offset; }; // Functions are not declared to minimize # of lines -static void WriteDataByte( struct GDS_Device* Device, uint8_t Data ) { - Device->WriteData( Device, &Data, 1); +static void WriteDataByte(struct GDS_Device* Device, uint8_t Data) { Device->WriteData(Device, &Data, 1); } + +static void SetColumnAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x15); + Device->WriteData(Device, &Start, 1); + Device->WriteData(Device, &End, 1); +} +static void SetRowAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x75); + Device->WriteData(Device, &Start, 1); + Device->WriteData(Device, &End, 1); } -static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x15 ); - Device->WriteData( Device, &Start, 1 ); - Device->WriteData( Device, &End, 1 ); -} -static void SetRowAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x75 ); - Device->WriteData( Device, &Start, 1 ); - Device->WriteData( Device, &End, 1 ); -} +static void Update(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + + // RAM is by columns of 4 pixels ... + SetColumnAddress(Device, Private->Offset, Private->Offset + Device->Width / 4 - 1); -static void Update( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - - // RAM is by columns of 4 pixels ... - SetColumnAddress( Device, Private->Offset, Private->Offset + Device->Width / 4 - 1); - #ifdef SHADOW_BUFFER - uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer; - bool dirty = false; - - for (int r = 0, page = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width always / by 2) - for (int c = Device->Width / 2 / 2; --c >= 0;) { - if (*optr != *iptr) { - dirty = true; - *optr = *iptr; - } - iptr++; optr++; - } - - // one line done, check for page boundary - if (++page == Private->PageSize) { - if (dirty) { - uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Private->Shadowbuffer + (r - page + 1) * Device->Width / 2); - SetRowAddress( Device, r - page + 1, r ); - for (int i = page * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8); - //memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 ); - Device->WriteCommand( Device, 0x5c ); - Device->WriteData( Device, Private->iRAM, Device->Width * page / 2 ); - dirty = false; - } - page = 0; - } - } + uint16_t *optr = (uint16_t*)Private->Shadowbuffer, *iptr = (uint16_t*)Device->Framebuffer; + bool dirty = false; + + for(int r = 0, page = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width always / by 2) + for(int c = Device->Width / 2 / 2; --c >= 0;) { + if(*optr != *iptr) { + dirty = true; + *optr = *iptr; + } + iptr++; + optr++; + } + + // one line done, check for page boundary + if(++page == Private->PageSize) { + if(dirty) { + uint16_t *optr = (uint16_t*)Private->iRAM, *iptr = (uint16_t*)(Private->Shadowbuffer + (r - page + 1) * Device->Width / 2); + SetRowAddress(Device, r - page + 1, r); + for(int i = page * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8); + //memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 ); + Device->WriteCommand(Device, 0x5c); + Device->WriteData(Device, Private->iRAM, Device->Width * page / 2); + dirty = false; + } + page = 0; + } + } #else - for (int r = 0; r < Device->Height; r += Private->PageSize) { - SetRowAddress( Device, r, r + Private->PageSize - 1 ); - Device->WriteCommand( Device, 0x5c ); - if (Private->iRAM) { - uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Device->Framebuffer + r * Device->Width / 2); - for (int i = Private->PageSize * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8); - //memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); - Device->WriteData( Device, Private->iRAM, Private->PageSize * Device->Width / 2 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); - } - } -#endif -} - -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); - Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); - Device->WriteCommand( Device, 0xA0 ); - Device->WriteData( Device, &Private->ReMap, 1 ); - WriteDataByte( Device, 0x11 ); - Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 ); -} - -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } - -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0xC1 ); - Device->WriteData( Device, &Contrast, 1 ); -} - -static bool Init( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - - // these displays seems to be layout centered (1 column = 4 pixels of 4 bits each, little endian) - Private->Offset = (480 - Device->Width) / 4 / 2; - - // find a page size that is not too small is an integer of height - Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2)); - while (Private->PageSize && Device->Height != (Device->Height / Private->PageSize) * Private->PageSize) Private->PageSize--; - -#ifdef SHADOW_BUFFER - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); + for(int r = 0; r < Device->Height; r += Private->PageSize) { + SetRowAddress(Device, r, r + Private->PageSize - 1); + Device->WriteCommand(Device, 0x5c); + if(Private->iRAM) { + uint16_t *optr = (uint16_t*)Private->iRAM, *iptr = (uint16_t*)(Device->Framebuffer + r * Device->Width / 2); + for(int i = Private->PageSize * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8); + //memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); + Device->WriteData(Device, Private->iRAM, Private->PageSize * Device->Width / 2); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2); + } + } #endif - Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); +} - ESP_LOGI(TAG, "SSD1322 with offset %u, page %u, iRAM %p", Private->Offset, Private->PageSize, Private->iRAM); - - // need to be off and disable display RAM - Device->DisplayOff( Device ); - Device->WriteCommand( Device, 0xA5 ); - - // Display Offset - Device->WriteCommand( Device, 0xA2 ); - WriteDataByte( Device, 0 ); - - // Display Start Line - Device->WriteCommand( Device, 0xA1 ); - WriteDataByte( Device, 0x00 ); - - // set flip modes - Private->ReMap = 0; - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - - // set Display Enhancement - Device->WriteCommand( Device, 0xB4 ); - WriteDataByte( Device, 0xA0 ); - WriteDataByte( Device, 0xB5 ); - - // set Clocks - Device->WriteCommand( Device, 0xB3 ); - WriteDataByte( Device, 0xB2 ); // 0x91 seems to be common but is too slow for 5.5' - - // set MUX - Device->WriteCommand( Device, 0xCA ); - WriteDataByte( Device, Device->Height - 1 ); - - // phase 1 & 2 period - Device->WriteCommand( Device, 0xB1 ); - WriteDataByte( Device, 0xE3 ); // 0xE2 was recommended - - // set pre-charge V - Device->WriteCommand( Device, 0xBB ); - WriteDataByte( Device, 0x0F); // 0x1F causes column interferences - - // set COM deselect voltage - Device->WriteCommand( Device, 0xBE ); - WriteDataByte( Device, 0x07 ); - - // no Display Inversion - Device->WriteCommand( Device, 0xA6 ); - - // gone with the wind - Device->DisplayOn( Device ); - Device->Update( Device ); - - return true; -} +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); + Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); + Device->WriteCommand(Device, 0xA0); + Device->WriteData(Device, &Private->ReMap, 1); + WriteDataByte(Device, 0x11); + Device->WriteCommand(Device, Layout->Invert ? 0xA7 : 0xA6); +} + +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAF); } +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAE); } + +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0xC1); + Device->WriteData(Device, &Contrast, 1); +} + +static bool Init(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + + // these displays seems to be layout centered (1 column = 4 pixels of 4 bits each, little endian) + Private->Offset = (480 - Device->Width) / 4 / 2; + + // find a page size that is not too small is an integer of height + Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2)); + while(Private->PageSize && Device->Height != (Device->Height / Private->PageSize) * Private->PageSize) Private->PageSize--; + +#ifdef SHADOW_BUFFER + Private->Shadowbuffer = malloc(Device->FramebufferSize); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +#endif + Private->iRAM = heap_caps_malloc(Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + + ESP_LOGI(TAG, "SSD1322 with offset %u, page %u, iRAM %p", Private->Offset, Private->PageSize, Private->iRAM); + + // need to be off and disable display RAM + Device->DisplayOff(Device); + Device->WriteCommand(Device, 0xA5); + + // Display Offset + Device->WriteCommand(Device, 0xA2); + WriteDataByte(Device, 0); + + // Display Start Line + Device->WriteCommand(Device, 0xA1); + WriteDataByte(Device, 0x00); + + // set flip modes + Private->ReMap = 0; + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); + + // set Display Enhancement + Device->WriteCommand(Device, 0xB4); + WriteDataByte(Device, 0xA0); + WriteDataByte(Device, 0xB5); + + // set Clocks + Device->WriteCommand(Device, 0xB3); + WriteDataByte(Device, 0xB2); // 0x91 seems to be common but is too slow for 5.5' + + // set MUX + Device->WriteCommand(Device, 0xCA); + WriteDataByte(Device, Device->Height - 1); + + // phase 1 & 2 period + Device->WriteCommand(Device, 0xB1); + WriteDataByte(Device, 0xE3); // 0xE2 was recommended + + // set pre-charge V + Device->WriteCommand(Device, 0xBB); + WriteDataByte(Device, 0x0F); // 0x1F causes column interferences + + // set COM deselect voltage + Device->WriteCommand(Device, 0xBE); + WriteDataByte(Device, 0x07); + + // no Display Inversion + Device->WriteCommand(Device, 0xA6); + + // gone with the wind + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} static const struct GDS_Device SSD1322 = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, - .SetLayout = SetLayout, - .Update = Update, .Init = Init, - .Mode = GDS_GRAYSCALE, .Depth = 4, -}; + .DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetContrast = SetContrast, + .SetLayout = SetLayout, + .Update = Update, + .Init = Init, + .Mode = GDS_GRAYSCALE, + .Depth = 4, +}; -struct GDS_Device* SSD1322_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - if(Driver->common.driver != sys_display_drivers_SSD1322) return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - - *Device = SSD1322; - - return Device; +struct GDS_Device* SSD1322_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + if(Driver->common.driver != sys_display_drivers_SSD1322) return NULL; + + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); + + *Device = SSD1322; + + return Device; } \ No newline at end of file diff --git a/components/display/SSD132x.c b/components/display/SSD132x.c index c0b32afc..9a31e141 100644 --- a/components/display/SSD132x.c +++ b/components/display/SSD132x.c @@ -18,334 +18,349 @@ #define SHADOW_BUFFER #define USE_IRAM -#define PAGE_BLOCK 1024 +#define PAGE_BLOCK 1024 -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) static char TAG[] = "SSD132x"; enum { SSD1326, SSD1327 }; struct PrivateSpace { - uint8_t *iRAM, *Shadowbuffer; - uint8_t ReMap, PageSize; - uint8_t Model; + uint8_t *iRAM, *Shadowbuffer; + uint8_t ReMap, PageSize; + uint8_t Model; }; -static const unsigned char BitReverseTable256[] = -{ - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; +static const unsigned char BitReverseTable256[] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; // Functions are not declared to minimize # of lines -static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x15 ); - Device->WriteCommand( Device, Start ); - Device->WriteCommand( Device, End ); +static void SetColumnAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x15); + Device->WriteCommand(Device, Start); + Device->WriteCommand(Device, End); } -static void SetRowAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - // can be by row, not by page (see Update Optimization) - Device->WriteCommand( Device, 0x75 ); - Device->WriteCommand( Device, Start ); - Device->WriteCommand( Device, End ); +static void SetRowAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + // can be by row, not by page (see Update Optimization) + Device->WriteCommand(Device, 0x75); + Device->WriteCommand(Device, Start); + Device->WriteCommand(Device, End); } -static void Update4( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - - // always update by full lines - SetColumnAddress( Device, 0, Device->Width / 2 - 1); - +static void Update4(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + + // always update by full lines + SetColumnAddress(Device, 0, Device->Width / 2 - 1); + #ifdef SHADOW_BUFFER - uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer; - bool dirty = false; - - for (int r = 0, page = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width always / by 2) - for (int c = Device->Width / 2 / 2; --c >= 0;) { - if (*optr != *iptr) { - dirty = true; - *optr = *iptr; - } - iptr++; optr++; - } - - // one line done, check for page boundary - if (++page == Private->PageSize) { - if (dirty) { - SetRowAddress( Device, r - page + 1, r ); - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 ); - Device->WriteData( Device, Private->iRAM, Device->Width * page / 2 ); - } else { - Device->WriteData( Device, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 ); - } - dirty = false; - } - page = 0; - } - } + uint16_t *optr = (uint16_t*)Private->Shadowbuffer, *iptr = (uint16_t*)Device->Framebuffer; + bool dirty = false; + + for(int r = 0, page = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width always / by 2) + for(int c = Device->Width / 2 / 2; --c >= 0;) { + if(*optr != *iptr) { + dirty = true; + *optr = *iptr; + } + iptr++; + optr++; + } + + // one line done, check for page boundary + if(++page == Private->PageSize) { + if(dirty) { + SetRowAddress(Device, r - page + 1, r); + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2); + Device->WriteData(Device, Private->iRAM, Device->Width * page / 2); + } else { + Device->WriteData(Device, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2); + } + dirty = false; + } + page = 0; + } + } #else - for (int r = 0; r < Device->Height; r += Private->PageSize) { - SetRowAddress( Device, r, r + Private->PageSize - 1 ); - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); - Device->WriteData( Device, Private->iRAM, Private->PageSize * Device->Width / 2 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); - } - } -#endif + for(int r = 0; r < Device->Height; r += Private->PageSize) { + SetRowAddress(Device, r, r + Private->PageSize - 1); + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2); + Device->WriteData(Device, Private->iRAM, Private->PageSize * Device->Width / 2); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2); + } + } +#endif } /* We have to make a choice here: either we go by row one by one and send lots of small packets on the serial interface or we do a page of N rows once at least a change has been detected. So far, choice is to go one-by-one -*/ -static void Update1( struct GDS_Device* Device ) { +*/ +static void Update1(struct GDS_Device* Device) { #ifdef SHADOW_BUFFER - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - // not sure the compiler does not have to redo all calculation in for loops, so local it is - int width = Device->Width / 8, rows = Device->Height; - uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer; - int CurrentRow = -1, FirstCol = -1, LastCol = -1; - - // by row, find first and last columns that have been updated - for (int r = 0; r < rows; r++) { - uint8_t first = 0, last; - for (int c = 0; c < width; c++) { - if (*iptr != *optr) { - if (!first) first = c + 1; - last = c ; - } - *optr++ = *iptr++; - } - - // now update the display by "byte rows" - if (first--) { - // only set column when useful, saves a fair bit of CPU - if (first > FirstCol && first <= FirstCol + 4 && last < LastCol && last >= LastCol - 4) { - first = FirstCol; - last = LastCol; - } else { - SetColumnAddress( Device, first, last ); - FirstCol = first; - LastCol = last; - } - - // Set row only when needed, otherwise let auto-increment work - if (r != CurrentRow) SetRowAddress( Device, r, Device->Height - 1 ); - CurrentRow = r + 1; - - // actual write - Device->WriteData( Device, Private->Shadowbuffer + r*width + first, last - first + 1 ); - } - } -#else - // automatic counter and end Row/Column - SetColumnAddress( Device, 0, Device->Width / 8 - 1); - SetRowAddress( Device, 0, Device->Height - 1); - Device->WriteData( Device, Device->Framebuffer, Device->FramebufferSize ); -#endif + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + // not sure the compiler does not have to redo all calculation in for loops, so local it is + int width = Device->Width / 8, rows = Device->Height; + uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer; + int CurrentRow = -1, FirstCol = -1, LastCol = -1; + + // by row, find first and last columns that have been updated + for(int r = 0; r < rows; r++) { + uint8_t first = 0, last; + for(int c = 0; c < width; c++) { + if(*iptr != *optr) { + if(!first) first = c + 1; + last = c; + } + *optr++ = *iptr++; + } + + // now update the display by "byte rows" + if(first--) { + // only set column when useful, saves a fair bit of CPU + if(first > FirstCol && first <= FirstCol + 4 && last < LastCol && last >= LastCol - 4) { + first = FirstCol; + last = LastCol; + } else { + SetColumnAddress(Device, first, last); + FirstCol = first; + LastCol = last; + } + + // Set row only when needed, otherwise let auto-increment work + if(r != CurrentRow) SetRowAddress(Device, r, Device->Height - 1); + CurrentRow = r + 1; + + // actual write + Device->WriteData(Device, Private->Shadowbuffer + r * width + first, last - first + 1); + } + } +#else + // automatic counter and end Row/Column + SetColumnAddress(Device, 0, Device->Width / 8 - 1); + SetRowAddress(Device, 0, Device->Height - 1); + Device->WriteData(Device, Device->Framebuffer, Device->FramebufferSize); +#endif } // in 1 bit mode, SSD1326 has a different memory map than SSD1306 and SH1106 -static void IRAM_ATTR _DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - uint32_t XBit = ( X & 0x07 ); - uint8_t* FBOffset = Device->Framebuffer + ( ( Y * Device->Width + X ) >> 3 ); +static void IRAM_ATTR _DrawPixel1Fast(struct GDS_Device* Device, int X, int Y, int Color) { + uint32_t XBit = (X & 0x07); + uint8_t* FBOffset = Device->Framebuffer + ((Y * Device->Width + X) >> 3); - if ( Color == GDS_COLOR_XOR ) { - *FBOffset ^= BIT( 7 - XBit ); + if(Color == GDS_COLOR_XOR) { + *FBOffset ^= BIT(7 - XBit); } else { - // we might be able to save the 7-Xbit using BitRemap (A0 bit 2) - *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( XBit ) : *FBOffset | BIT( XBit ); + // we might be able to save the 7-Xbit using BitRemap (A0 bit 2) + *FBOffset = (Color == GDS_COLOR_BLACK) ? *FBOffset & ~BIT(XBit) : *FBOffset | BIT(XBit); } } -static void ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) { - uint8_t _Color = Color == GDS_COLOR_BLACK ? 0: 0xff; - int Width = Device->Width >> 3; - uint8_t *optr = Device->Framebuffer; - - for (int r = y1; r <= y2; r++) { - int c = x1; - // for a row that is not on a boundary, not column opt can be done, so handle all columns on that line - while (c & 0x07 && c <= x2) _DrawPixel1Fast( Device, c++, r, Color ); - // at this point we are aligned on column boundary - int chunk = (x2 - c + 1) >> 3; - memset(optr + Width * r + (c >> 3), _Color, chunk ); - c += chunk * 8; - while (c <= x2) _DrawPixel1Fast( Device, c++, r, Color ); - } +static void ClearWindow(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color) { + uint8_t _Color = Color == GDS_COLOR_BLACK ? 0 : 0xff; + int Width = Device->Width >> 3; + uint8_t* optr = Device->Framebuffer; + + for(int r = y1; r <= y2; r++) { + int c = x1; + // for a row that is not on a boundary, not column opt can be done, so handle all columns on that line + while(c & 0x07 && c <= x2) _DrawPixel1Fast(Device, c++, r, Color); + // at this point we are aligned on column boundary + int chunk = (x2 - c + 1) >> 3; + memset(optr + Width * r + (c >> 3), _Color, chunk); + c += chunk * 8; + while(c <= x2) _DrawPixel1Fast(Device, c++, r, Color); + } } -static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) { - if (!Height) Height = Device->Height; - if (!Width) Width = Device->Width; - int DWidth = Device->Width >> 3; - - // Two consecutive bits of source data are split over two different bytes of framebuffer - for (int c = 0; c < Width; c++) { - uint8_t shift = c & 0x07, bit = ~(1 << shift); - uint8_t *optr = Device->Framebuffer + (c >> 3); - - // we need to linearize code to let compiler better optimize - for (int r = Height >> 3; --r >= 0;) { - uint8_t Byte = BitReverseTable256[*Data++]; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; - *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; - } - } +static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t* Data, int Width, int Height, int Color) { + if(!Height) Height = Device->Height; + if(!Width) Width = Device->Width; + int DWidth = Device->Width >> 3; + + // Two consecutive bits of source data are split over two different bytes of framebuffer + for(int c = 0; c < Width; c++) { + uint8_t shift = c & 0x07, bit = ~(1 << shift); + uint8_t* optr = Device->Framebuffer + (c >> 3); + + // we need to linearize code to let compiler better optimize + for(int r = Height >> 3; --r >= 0;) { + uint8_t Byte = BitReverseTable256[*Data++]; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); + optr += DWidth; + } + } } -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - if (Private->Model == SSD1326) { - Private->ReMap = Layout->HFlip ? (Private->ReMap | ((1 << 0) | (1 << 2))) : (Private->ReMap & ~((1 << 0) | (1 << 2))); - Private->ReMap = Layout->HFlip ? (Private->ReMap | (1 << 1)) : (Private->ReMap & ~(1 << 1)); - } else { - Private->ReMap = Layout->VFlip ? (Private->ReMap | ((1 << 0) | (1 << 1))) : (Private->ReMap & ~((1 << 0) | (1 << 1))); - Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); - } - Device->WriteCommand( Device, 0xA0 ); - Device->WriteCommand( Device, Private->ReMap ); - Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA4 ); -} - -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } - -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0x81 ); - Device->WriteCommand( Device, Contrast ); +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + if(Private->Model == SSD1326) { + Private->ReMap = Layout->HFlip ? (Private->ReMap | ((1 << 0) | (1 << 2))) : (Private->ReMap & ~((1 << 0) | (1 << 2))); + Private->ReMap = Layout->HFlip ? (Private->ReMap | (1 << 1)) : (Private->ReMap & ~(1 << 1)); + } else { + Private->ReMap = Layout->VFlip ? (Private->ReMap | ((1 << 0) | (1 << 1))) : (Private->ReMap & ~((1 << 0) | (1 << 1))); + Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); + } + Device->WriteCommand(Device, 0xA0); + Device->WriteCommand(Device, Private->ReMap); + Device->WriteCommand(Device, Layout->Invert ? 0xA7 : 0xA4); } -static bool Init( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - - // find a page size that is not too small is an integer of height - Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2)); - while (Private->PageSize && Device->Height != (Device->Height / Private->PageSize) * Private->PageSize) Private->PageSize--; - -#ifdef SHADOW_BUFFER +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAF); } +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAE); } + +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0x81); + Device->WriteCommand(Device, Contrast); +} + +static bool Init(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + + // find a page size that is not too small is an integer of height + Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2)); + while(Private->PageSize && Device->Height != (Device->Height / Private->PageSize) * Private->PageSize) Private->PageSize--; + +#ifdef SHADOW_BUFFER #ifdef USE_IRAM - if (Device->IF == GDS_IF_SPI) { - if (Device->Depth == 1) { - Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); - } else { - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); - } - } else + if(Device->IF == GDS_IF_SPI) { + if(Device->Depth == 1) { + Private->Shadowbuffer = heap_caps_malloc(Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + } else { + Private->Shadowbuffer = malloc(Device->FramebufferSize); + Private->iRAM = heap_caps_malloc(Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + } + } else #endif - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); + Private->Shadowbuffer = malloc(Device->FramebufferSize); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); #else -#ifdef USE_IRAM - if (Device->Depth == 4 && Device->IF == GDS_IF_SPI) Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); -#endif +#ifdef USE_IRAM + if(Device->Depth == 4 && Device->IF == GDS_IF_SPI) + Private->iRAM = heap_caps_malloc(Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); +#endif #endif - ESP_LOGI(TAG, "SSD1326/7 with bit depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM); - - // need to be off and disable display RAM - Device->DisplayOff( Device ); - Device->WriteCommand( Device, 0xA5 ); - - // need COM split (6) - Private->ReMap = 1 << 6; - // MUX Ratio - Device->WriteCommand( Device, 0xA8 ); - Device->WriteCommand( Device, Device->Height - 1); - // Display Offset - Device->WriteCommand( Device, 0xA2 ); - Device->WriteCommand( Device, 0 ); - // Display Start Line - Device->WriteCommand( Device, 0xA1 ); - Device->WriteCommand( Device, 0x00 ); - Device->SetContrast( Device, 0x7F ); - // set flip modes - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - // no Display Inversion - Device->WriteCommand( Device, 0xA6 ); - // set Clocks - Device->WriteCommand( Device, 0xB3 ); - Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); - // set Adressing Mode Horizontal - Private->ReMap |= (0 << 2); - // set monotchrome mode if required - if (Device->Depth == 1) Private->ReMap |= (1 << 4); - // write ReMap byte - Device->WriteCommand( Device, 0xA0 ); - Device->WriteCommand( Device, Private->ReMap ); - - // gone with the wind - Device->WriteCommand( Device, 0xA4 ); - Device->DisplayOn( Device ); - Device->Update( Device ); - - return true; -} + ESP_LOGI(TAG, "SSD1326/7 with bit depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM); + + // need to be off and disable display RAM + Device->DisplayOff(Device); + Device->WriteCommand(Device, 0xA5); + + // need COM split (6) + Private->ReMap = 1 << 6; + // MUX Ratio + Device->WriteCommand(Device, 0xA8); + Device->WriteCommand(Device, Device->Height - 1); + // Display Offset + Device->WriteCommand(Device, 0xA2); + Device->WriteCommand(Device, 0); + // Display Start Line + Device->WriteCommand(Device, 0xA1); + Device->WriteCommand(Device, 0x00); + Device->SetContrast(Device, 0x7F); + // set flip modes + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); + // no Display Inversion + Device->WriteCommand(Device, 0xA6); + // set Clocks + Device->WriteCommand(Device, 0xB3); + Device->WriteCommand(Device, (0x08 << 4) | 0x00); + // set Adressing Mode Horizontal + Private->ReMap |= (0 << 2); + // set monotchrome mode if required + if(Device->Depth == 1) Private->ReMap |= (1 << 4); + // write ReMap byte + Device->WriteCommand(Device, 0xA0); + Device->WriteCommand(Device, Private->ReMap); + + // gone with the wind + Device->WriteCommand(Device, 0xA4); + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} static const struct GDS_Device SSD132x = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, - .SetLayout = SetLayout, - .Update = Update4, .Init = Init, - .Mode = GDS_GRAYSCALE, .Depth = 4, -}; + .DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetContrast = SetContrast, + .SetLayout = SetLayout, + .Update = Update4, + .Init = Init, + .Mode = GDS_GRAYSCALE, + .Depth = 4, +}; -struct GDS_Device* SSD132x_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - uint8_t Model; - int Depth; - - if(Driver->common.driver == sys_display_drivers_SSD1326) Model = SSD1326; - else if(Driver->common.driver == sys_display_drivers_SSD1327) Model = SSD1327; - return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - - *Device = SSD132x; - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - Private->Model = Model; - - Depth = Driver->common.bitDepth != 0?Driver->common.bitDepth:1; - - if (Model == SSD1326 && Depth == 1) { - Device->Update = Update1; - Device->DrawPixelFast = _DrawPixel1Fast; - Device->DrawBitmapCBR = DrawBitmapCBR; - Device->ClearWindow = ClearWindow; - Device->Depth = 1; - Device->Mode = GDS_MONO; -#if !defined SHADOW_BUFFER && defined USE_IRAM - Device->Alloc = GDS_ALLOC_IRAM_SPI; -#endif - } - - return Device; +struct GDS_Device* SSD132x_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + uint8_t Model; + int Depth; + + if(Driver->common.driver == sys_display_drivers_SSD1326) + Model = SSD1326; + else if(Driver->common.driver == sys_display_drivers_SSD1327) + Model = SSD1327; + return NULL; + + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); + + *Device = SSD132x; + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + Private->Model = Model; + + Depth = Driver->common.bitDepth != 0 ? Driver->common.bitDepth : 1; + + if(Model == SSD1326 && Depth == 1) { + Device->Update = Update1; + Device->DrawPixelFast = _DrawPixel1Fast; + Device->DrawBitmapCBR = DrawBitmapCBR; + Device->ClearWindow = ClearWindow; + Device->Depth = 1; + Device->Mode = GDS_MONO; +#if !defined SHADOW_BUFFER && defined USE_IRAM + Device->Alloc = GDS_ALLOC_IRAM_SPI; +#endif + } + + return Device; } \ No newline at end of file diff --git a/components/display/SSD1351.c b/components/display/SSD1351.c index d692c02a..d4374733 100644 --- a/components/display/SSD1351.c +++ b/components/display/SSD1351.c @@ -18,271 +18,277 @@ #define SHADOW_BUFFER #define USE_IRAM -#define PAGE_BLOCK 2048 -#define ENABLE_WRITE 0x5c +#define PAGE_BLOCK 2048 +#define ENABLE_WRITE 0x5c -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) static char TAG[] = "SSD1351"; struct PrivateSpace { - uint8_t *iRAM, *Shadowbuffer; - uint8_t ReMap, PageSize; + uint8_t *iRAM, *Shadowbuffer; + uint8_t ReMap, PageSize; }; // Functions are not declared to minimize # of lines -static void WriteByte( struct GDS_Device* Device, uint8_t Data ) { - Device->WriteData( Device, &Data, 1 ); +static void WriteByte(struct GDS_Device* Device, uint8_t Data) { Device->WriteData(Device, &Data, 1); } + +static void SetColumnAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x15); + WriteByte(Device, Start); + WriteByte(Device, End); +} +static void SetRowAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + Device->WriteCommand(Device, 0x75); + WriteByte(Device, Start); + WriteByte(Device, End); } -static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x15 ); - WriteByte( Device, Start ); - WriteByte( Device, End ); -} -static void SetRowAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - Device->WriteCommand( Device, 0x75 ); - WriteByte( Device, Start ); - WriteByte( Device, End ); -} +static void Update16(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; -static void Update16( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - #ifdef SHADOW_BUFFER - uint32_t *optr = (uint32_t*) Private->Shadowbuffer, *iptr = (uint32_t*) Device->Framebuffer; - int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - - for (int r = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width is always a multiple of 2) - for (int c = 0; c < Device->Width / 2; c++, iptr++, optr++) { - if (*optr != *iptr) { - *optr = *iptr; - if (c < FirstCol) FirstCol = c; - if (c > LastCol) LastCol = c; - if (FirstRow < 0) FirstRow = r; - LastRow = r; - } - } + uint32_t *optr = (uint32_t*)Private->Shadowbuffer, *iptr = (uint32_t*)Device->Framebuffer; + int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - // wait for a large enough window - careful that window size might increase by more than a line at once ! - if (FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; - - FirstCol *= 2; - LastCol = LastCol * 2 + 1; - SetRowAddress( Device, FirstRow, LastRow ); - SetColumnAddress( Device, FirstCol, LastCol ); - Device->WriteCommand( Device, ENABLE_WRITE ); - - int ChunkSize = (LastCol - FirstCol + 1) * 2; - - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - uint8_t *optr = Private->iRAM; - for (int i = FirstRow; i <= LastRow; i++) { - memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); - optr += ChunkSize; - if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue; - Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); - optr = Private->iRAM; - } - } else for (int i = FirstRow; i <= LastRow; i++) { - Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize ); - } + for(int r = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width is always a multiple of 2) + for(int c = 0; c < Device->Width / 2; c++, iptr++, optr++) { + if(*optr != *iptr) { + *optr = *iptr; + if(c < FirstCol) FirstCol = c; + if(c > LastCol) LastCol = c; + if(FirstRow < 0) FirstRow = r; + LastRow = r; + } + } - FirstCol = Device->Width / 2; LastCol = 0; - FirstRow = -1; - } + // wait for a large enough window - careful that window size might increase by more than a line at once ! + if(FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; + + FirstCol *= 2; + LastCol = LastCol * 2 + 1; + SetRowAddress(Device, FirstRow, LastRow); + SetColumnAddress(Device, FirstCol, LastCol); + Device->WriteCommand(Device, ENABLE_WRITE); + + int ChunkSize = (LastCol - FirstCol + 1) * 2; + + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + uint8_t* optr = Private->iRAM; + for(int i = FirstRow; i <= LastRow; i++) { + memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); + optr += ChunkSize; + if(optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue; + Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); + optr = Private->iRAM; + } + } else + for(int i = FirstRow; i <= LastRow; i++) { + Device->WriteData(Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); + } + + FirstCol = Device->Width / 2; + LastCol = 0; + FirstRow = -1; + } #else - // always update by full lines - SetColumnAddress( Device, 0, Device->Width - 1); - - for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { - int Height = min(Private->PageSize, Device->Height - r); - - SetRowAddress( Device, r, r + Height - 1 ); - Device->WriteCommand(Device, ENABLE_WRITE); - - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 ); - Device->WriteData( Device, Private->iRAM, Height * Device->Width * 2 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 ); - } - } -#endif + // always update by full lines + SetColumnAddress(Device, 0, Device->Width - 1); + + for(int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { + int Height = min(Private->PageSize, Device->Height - r); + + SetRowAddress(Device, r, r + Height - 1); + Device->WriteCommand(Device, ENABLE_WRITE); + + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2); + Device->WriteData(Device, Private->iRAM, Height * Device->Width * 2); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2); + } + } +#endif } -static void Update24( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - +static void Update24(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0; + #ifdef SHADOW_BUFFER - uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer; - - for (int r = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width always / by 2) - for (int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) { - if (*optr != *iptr) { - *optr = *iptr; - if (c < FirstCol) FirstCol = c; - if (c > LastCol) LastCol = c; - if (FirstRow < 0) FirstRow = r; - LastRow = r; - } - } - - // do we have enough to send (cols are divided by 3/2) - if (FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2 + 3 - 1) / 3) * (r - FirstRow + 1) * 3 < PAGE_BLOCK && r != Device->Height - 1)) continue; - - FirstCol = (FirstCol * 2) / 3; - LastCol = (LastCol * 2 + 1) / 3; - SetRowAddress( Device, FirstRow, LastRow ); - SetColumnAddress( Device, FirstCol, LastCol ); - Device->WriteCommand( Device, ENABLE_WRITE ); - - int ChunkSize = (LastCol - FirstCol + 1) * 3; - - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - uint8_t *optr = Private->iRAM; - for (int i = FirstRow; i <= LastRow; i++) { - memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); - optr += ChunkSize; - if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue; - Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); - optr = Private->iRAM; - } - } else for (int i = FirstRow; i <= LastRow; i++) { - Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize ); - } + uint16_t *optr = (uint16_t*)Private->Shadowbuffer, *iptr = (uint16_t*)Device->Framebuffer; - FirstCol = (Device->Width * 3) / 2; LastCol = 0; - FirstRow = -1; - } + for(int r = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width always / by 2) + for(int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) { + if(*optr != *iptr) { + *optr = *iptr; + if(c < FirstCol) FirstCol = c; + if(c > LastCol) LastCol = c; + if(FirstRow < 0) FirstRow = r; + LastRow = r; + } + } + + // do we have enough to send (cols are divided by 3/2) + if(FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2 + 3 - 1) / 3) * (r - FirstRow + 1) * 3 < PAGE_BLOCK && r != Device->Height - 1)) continue; + + FirstCol = (FirstCol * 2) / 3; + LastCol = (LastCol * 2 + 1) / 3; + SetRowAddress(Device, FirstRow, LastRow); + SetColumnAddress(Device, FirstCol, LastCol); + Device->WriteCommand(Device, ENABLE_WRITE); + + int ChunkSize = (LastCol - FirstCol + 1) * 3; + + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + uint8_t* optr = Private->iRAM; + for(int i = FirstRow; i <= LastRow; i++) { + memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); + optr += ChunkSize; + if(optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue; + Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); + optr = Private->iRAM; + } + } else + for(int i = FirstRow; i <= LastRow; i++) { + Device->WriteData(Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); + } + + FirstCol = (Device->Width * 3) / 2; + LastCol = 0; + FirstRow = -1; + } #else - // always update by full lines - SetColumnAddress( Device, 0, Device->Width - 1); - - for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { - int Height = min(Private->PageSize, Device->Height - r); - - SetRowAddress( Device, r, r + Height - 1 ); - Device->WriteCommand(Device, ENABLE_WRITE); - - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 ); - Device->WriteData( Device, Private->iRAM, Height * Device->Width * 3 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 ); - } - } -#endif + // always update by full lines + SetColumnAddress(Device, 0, Device->Width - 1); + + for(int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { + int Height = min(Private->PageSize, Device->Height - r); + + SetRowAddress(Device, r, r + Height - 1); + Device->WriteCommand(Device, ENABLE_WRITE); + + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3); + Device->WriteData(Device, Private->iRAM, Height * Device->Width * 3); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3); + } + } +#endif } -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); - Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); - Device->WriteCommand( Device, 0xA0 ); - WriteByte( Device, Private->ReMap ); - Device->WriteCommand( Device, Layout->Invert ? 0xA7 : 0xA6 ); -} - -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } - -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0xC7 ); - WriteByte( Device, Contrast >> 4); +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + Private->ReMap = Layout->HFlip ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); + Private->ReMap = Layout->VFlip ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); + Device->WriteCommand(Device, 0xA0); + WriteByte(Device, Private->ReMap); + Device->WriteCommand(Device, Layout->Invert ? 0xA7 : 0xA6); } -static bool Init( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - int Depth = (Device->Depth + 8 - 1) / 8; - - Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth)); - -#ifdef SHADOW_BUFFER - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAF); } +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0xAE); } + +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0xC7); + WriteByte(Device, Contrast >> 4); +} + +static bool Init(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + int Depth = (Device->Depth + 8 - 1) / 8; + + Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth)); + +#ifdef SHADOW_BUFFER + Private->Shadowbuffer = malloc(Device->FramebufferSize); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); #endif #ifdef USE_IRAM - Private->iRAM = heap_caps_malloc( (Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); + Private->iRAM = heap_caps_malloc((Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); #endif - ESP_LOGI(TAG, "SSD1351 with bit depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM); - - // unlock (specially 0xA2) - Device->WriteCommand( Device, 0xFD); - WriteByte(Device, 0xB1); - - // set clocks - /* + ESP_LOGI(TAG, "SSD1351 with bit depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM); + + // unlock (specially 0xA2) + Device->WriteCommand(Device, 0xFD); + WriteByte(Device, 0xB1); + + // set clocks + /* Device->WriteCommand( Device, 0xB3 ); WriteByte( Device, ( 0x08 << 4 ) | 0x00 ); */ - // need to be off and disable display RAM - Device->DisplayOff( Device ); + // need to be off and disable display RAM + Device->DisplayOff(Device); - // need COM split (5) - Private->ReMap = (1 << 5); - - // Display Offset - Device->WriteCommand( Device, 0xA2 ); - WriteByte( Device, 0x00 ); + // need COM split (5) + Private->ReMap = (1 << 5); - // Display Start Line - Device->WriteCommand( Device, 0xA1 ); - WriteByte( Device, 0x00 ); - - // set flip modes & contrast - Device->SetContrast( Device, 0x7F ); - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - - // set Adressing Mode Horizontal - Private->ReMap |= (0 << 2); - // set screen depth (16/18) - if (Device->Depth == 24) Private->ReMap |= (0x02 << 6); - // write ReMap byte - Device->WriteCommand( Device, 0xA0 ); - WriteByte( Device, Private->ReMap ); - - // no Display Inversion - Device->WriteCommand( Device, 0xA6 ); - - // gone with the wind - Device->DisplayOn( Device ); - Device->Update( Device ); - - return true; -} + // Display Offset + Device->WriteCommand(Device, 0xA2); + WriteByte(Device, 0x00); + + // Display Start Line + Device->WriteCommand(Device, 0xA1); + WriteByte(Device, 0x00); + + // set flip modes & contrast + Device->SetContrast(Device, 0x7F); + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); + + // set Adressing Mode Horizontal + Private->ReMap |= (0 << 2); + // set screen depth (16/18) + if(Device->Depth == 24) Private->ReMap |= (0x02 << 6); + // write ReMap byte + Device->WriteCommand(Device, 0xA0); + WriteByte(Device, Private->ReMap); + + // no Display Inversion + Device->WriteCommand(Device, 0xA6); + + // gone with the wind + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} static const struct GDS_Device SSD1351 = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, - .SetLayout = SetLayout, - .Update = Update16, .Init = Init, - .Mode = GDS_RGB565, .Depth = 16, -}; + .DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetContrast = SetContrast, + .SetLayout = SetLayout, + .Update = Update16, + .Init = Init, + .Mode = GDS_RGB565, + .Depth = 16, +}; -struct GDS_Device* SSD1351_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - int Depth; - - if(Driver->common.driver != sys_display_drivers_SSD1351) return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - - *Device = SSD1351; - Depth = Driver->common.bitDepth != 0?Driver->common.bitDepth:18; - - if (Depth == 18) { - Device->Mode = GDS_RGB666; - Device->Depth = 24; - Device->Update = Update24; - } - - return Device; +struct GDS_Device* SSD1351_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + int Depth; + + if(Driver->common.driver != sys_display_drivers_SSD1351) return NULL; + + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); + + *Device = SSD1351; + Depth = Driver->common.bitDepth != 0 ? Driver->common.bitDepth : 18; + + if(Depth == 18) { + Device->Mode = GDS_RGB666; + Device->Depth = 24; + Device->Update = Update24; + } + + return Device; } \ No newline at end of file diff --git a/components/display/SSD1675.c b/components/display/SSD1675.c index c219395a..62d59809 100644 --- a/components/display/SSD1675.c +++ b/components/display/SSD1675.c @@ -22,209 +22,328 @@ static char TAG[] = "SSD1675"; const unsigned char EPD_lut_full_update[] = { - 0x80,0x60,0x40,0x00,0x00,0x00,0x00, //LUT0: BB: VS 0 ~7 - 0x10,0x60,0x20,0x00,0x00,0x00,0x00, //LUT1: BW: VS 0 ~7 - 0x80,0x60,0x40,0x00,0x00,0x00,0x00, //LUT2: WB: VS 0 ~7 - 0x10,0x60,0x20,0x00,0x00,0x00,0x00, //LUT3: WW: VS 0 ~7 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00, //LUT4: VCOM: VS 0 ~7 - 0x03,0x03,0x00,0x00,0x02, // TP0 A~D RP0 - 0x09,0x09,0x00,0x00,0x02, // TP1 A~D RP1 - 0x03,0x03,0x00,0x00,0x02, // TP2 A~D RP2 - 0x00,0x00,0x00,0x00,0x00, // TP3 A~D RP3 - 0x00,0x00,0x00,0x00,0x00, // TP4 A~D RP4 - 0x00,0x00,0x00,0x00,0x00, // TP5 A~D RP5 - 0x00,0x00,0x00,0x00,0x00, // TP6 A~D RP6 - 0x15,0x41,0xA8,0x32,0x30,0x0A, + 0x80, + 0x60, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, //LUT0: BB: VS 0 ~7 + 0x10, + 0x60, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, //LUT1: BW: VS 0 ~7 + 0x80, + 0x60, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, //LUT2: WB: VS 0 ~7 + 0x10, + 0x60, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, //LUT3: WW: VS 0 ~7 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //LUT4: VCOM: VS 0 ~7 + 0x03, + 0x03, + 0x00, + 0x00, + 0x02, // TP0 A~D RP0 + 0x09, + 0x09, + 0x00, + 0x00, + 0x02, // TP1 A~D RP1 + 0x03, + 0x03, + 0x00, + 0x00, + 0x02, // TP2 A~D RP2 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP3 A~D RP3 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP4 A~D RP4 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP5 A~D RP5 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP6 A~D RP6 + 0x15, + 0x41, + 0xA8, + 0x32, + 0x30, + 0x0A, }; -const unsigned char EPD_lut_partial_update[]= { //20 bytes - 0x00,0x00,0x00,0x00,0x00,0x00,0x00, //LUT0: BB: VS 0 ~7 - 0x80,0x00,0x00,0x00,0x00,0x00,0x00, //LUT1: BW: VS 0 ~7 - 0x40,0x00,0x00,0x00,0x00,0x00,0x00, //LUT2: WB: VS 0 ~7 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00, //LUT3: WW: VS 0 ~7 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00, //LUT4: VCOM: VS 0 ~7 - 0x0A,0x00,0x00,0x00,0x00, // TP0 A~D RP0 - 0x00,0x00,0x00,0x00,0x00, // TP1 A~D RP1 - 0x00,0x00,0x00,0x00,0x00, // TP2 A~D RP2 - 0x00,0x00,0x00,0x00,0x00, // TP3 A~D RP3 - 0x00,0x00,0x00,0x00,0x00, // TP4 A~D RP4 - 0x00,0x00,0x00,0x00,0x00, // TP5 A~D RP5 - 0x00,0x00,0x00,0x00,0x00, // TP6 A~D RP6 - 0x15,0x41,0xA8,0x32,0x30,0x0A, +const unsigned char EPD_lut_partial_update[] = { + //20 bytes + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //LUT0: BB: VS 0 ~7 + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //LUT1: BW: VS 0 ~7 + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //LUT2: WB: VS 0 ~7 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //LUT3: WW: VS 0 ~7 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //LUT4: VCOM: VS 0 ~7 + 0x0A, + 0x00, + 0x00, + 0x00, + 0x00, // TP0 A~D RP0 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP1 A~D RP1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP2 A~D RP2 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP3 A~D RP3 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP4 A~D RP4 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP5 A~D RP5 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // TP6 A~D RP6 + 0x15, + 0x41, + 0xA8, + 0x32, + 0x30, + 0x0A, }; struct PrivateSpace { - int ReadyPin; - uint16_t Height; + int ReadyPin; + uint16_t Height; }; // Functions are not declared to minimize # of lines -void WaitReady( struct GDS_Device* Device) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - if (Private->ReadyPin >= 0) { - int count = 4*1000; - while (gpio_get_level( Private->ReadyPin ) && count) { - vTaskDelay( pdMS_TO_TICKS(100) ); - count -= 100; - } - } else { - vTaskDelay( pdMS_TO_TICKS(2000) ); - } -} - -static void WriteByte( struct GDS_Device* Device, uint8_t Data ) { - Device->WriteData( Device, &Data, 1 ); +void WaitReady(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + if(Private->ReadyPin >= 0) { + int count = 4 * 1000; + while(gpio_get_level(Private->ReadyPin) && count) { + vTaskDelay(pdMS_TO_TICKS(100)); + count -= 100; + } + } else { + vTaskDelay(pdMS_TO_TICKS(2000)); + } } -static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { - // start might be greater than end if we decrement - Device->WriteCommand( Device, 0x44 ); - Device->WriteData( Device, &Start, 1 ); - Device->WriteData( Device, &End, 1 ); - - // we obviously want to start ... from the start - Device->WriteCommand( Device, 0x4e ); - WriteByte( Device, Start ); +static void WriteByte(struct GDS_Device* Device, uint8_t Data) { Device->WriteData(Device, &Data, 1); } + +static void SetColumnAddress(struct GDS_Device* Device, uint8_t Start, uint8_t End) { + // start might be greater than end if we decrement + Device->WriteCommand(Device, 0x44); + Device->WriteData(Device, &Start, 1); + Device->WriteData(Device, &End, 1); + + // we obviously want to start ... from the start + Device->WriteCommand(Device, 0x4e); + WriteByte(Device, Start); } -static void SetRowAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) { - // start might be greater than end if we decrement - Device->WriteCommand( Device, 0x45 ); - WriteByte( Device, Start ); - WriteByte( Device, Start >> 8 ); - WriteByte( Device, End ); - WriteByte( Device, End >> 8 ); - - // we obviously want to start ... from the start - Device->WriteCommand( Device, 0x4f ); - WriteByte( Device, Start ); - WriteByte( Device, Start >> 8 ); +static void SetRowAddress(struct GDS_Device* Device, uint16_t Start, uint16_t End) { + // start might be greater than end if we decrement + Device->WriteCommand(Device, 0x45); + WriteByte(Device, Start); + WriteByte(Device, Start >> 8); + WriteByte(Device, End); + WriteByte(Device, End >> 8); + + // we obviously want to start ... from the start + Device->WriteCommand(Device, 0x4f); + WriteByte(Device, Start); + WriteByte(Device, Start >> 8); } -static void Update( struct GDS_Device* Device ) { - uint8_t *iptr = Device->Framebuffer; - - Device->WriteCommand( Device, 0x24 ); - - // this is awfully slow, but e-ink are slow anyway ... - for (int i = Device->FramebufferSize; --i >= 0;) { - WriteByte( Device, ~*iptr++ ); - } - - Device->WriteCommand( Device, 0x22 ); - WriteByte( Device, 0xC7); - Device->WriteCommand( Device, 0X20 ); +static void Update(struct GDS_Device* Device) { + uint8_t* iptr = Device->Framebuffer; - WaitReady( Device ); + Device->WriteCommand(Device, 0x24); + + // this is awfully slow, but e-ink are slow anyway ... + for(int i = Device->FramebufferSize; --i >= 0;) { WriteByte(Device, ~*iptr++); } + + Device->WriteCommand(Device, 0x22); + WriteByte(Device, 0xC7); + Device->WriteCommand(Device, 0X20); + + WaitReady(Device); } // remember that for these ELD drivers W and H are "inverted" -static inline void _DrawPixel( struct GDS_Device* Device, int X, int Y, int Color ) { - uint32_t YBit = ( Y & 0x07 ); - Y>>= 3; +static inline void _DrawPixel(struct GDS_Device* Device, int X, int Y, int Color) { + uint32_t YBit = (Y & 0x07); + Y >>= 3; - uint8_t* FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X ); - *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( 7-YBit ) : *FBOffset | BIT( 7-YBit ); -} - -static void ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) { - for (int r = y1; r <= y2; r++) { - for (int c = x1; c <= x2; c++) { - _DrawPixel( Device, c, r, Color ); - } - } + uint8_t* FBOffset = Device->Framebuffer + ((Y * Device->Width) + X); + *FBOffset = (Color == GDS_COLOR_BLACK) ? *FBOffset & ~BIT(7 - YBit) : *FBOffset | BIT(7 - YBit); } -static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) { - if (!Height) Height = Device->Height; - if (!Width) Width = Device->Width; - - // just do row/column swap - for (int r = 0; r < Height; r++) { - uint8_t *optr = Device->Framebuffer + r*Device->Width, *iptr = Data + r; - for (int c = Width; --c >= 0;) { - *optr++ = *iptr; - iptr += Height; - } - } +static void ClearWindow(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color) { + for(int r = y1; r <= y2; r++) { + for(int c = x1; c <= x2; c++) { _DrawPixel(Device, c, r, Color); } + } } -static bool Init( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - - // need to re-adjust framebuffer because these are non % 8 - Private->Height = Device->Height; - if (Device->Height & 0x07) Device->Height = ((Device->Height >> 3) + 1) << 3; - - Device->FramebufferSize = Device->Width * Device->Height / 8; - Device->Framebuffer = calloc(1, Device->FramebufferSize); - NullCheck( Device->Framebuffer, return false ); - - if (Private->ReadyPin >= 0) { - esp_rom_gpio_pad_select_gpio( Private->ReadyPin ); - gpio_set_pull_mode( Private->ReadyPin, GPIO_PULLUP_ONLY); - gpio_set_direction( Private->ReadyPin, GPIO_MODE_INPUT ); - } - - // soft reset - vTaskDelay(pdMS_TO_TICKS( 2000 )); - Device->WriteCommand( Device, 0x12 ); - WaitReady( Device ); - - Device->WriteCommand( Device, 0x74 ); - WriteByte( Device, 0x54 ); - Device->WriteCommand( Device, 0x7e ); - WriteByte( Device, 0x3B ); - - Device->WriteCommand( Device, 0x3c ); - WriteByte( Device, 0x03 ); - - Device->WriteCommand( Device, 0x2c ); - WriteByte( Device, 0x55 ); +static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t* Data, int Width, int Height, int Color) { + if(!Height) Height = Device->Height; + if(!Width) Width = Device->Width; - Device->WriteCommand( Device, 0x03 ); - WriteByte( Device, EPD_lut_full_update[70] ); - - Device->WriteCommand( Device, 0x04 ); - WriteByte( Device, EPD_lut_full_update[71] ); - WriteByte( Device, EPD_lut_full_update[72] ); - WriteByte( Device, EPD_lut_full_update[73] ); - - Device->WriteCommand( Device, 0x3a ); - WriteByte( Device, EPD_lut_full_update[74] ); - Device->WriteCommand( Device, 0x3b ); - WriteByte( Device, EPD_lut_full_update[75] ); - - Device->WriteCommand( Device, 0X32 ); - for (int i = 0; i < 70; i++) { - WriteByte( Device, EPD_lut_full_update[i] ); - } + // just do row/column swap + for(int r = 0; r < Height; r++) { + uint8_t *optr = Device->Framebuffer + r * Device->Width, *iptr = Data + r; + for(int c = Width; --c >= 0;) { + *optr++ = *iptr; + iptr += Height; + } + } +} - // now deal with funny X/Y layout (W and H are "inverted") - Device->WriteCommand( Device, 0x01 ); - WriteByte( Device, Device->Width - 1 ); - WriteByte( Device, (Device->Width - 1) >> 8 ); - WriteByte( Device, (0 << 0) ); +static bool Init(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; - /* + // need to re-adjust framebuffer because these are non % 8 + Private->Height = Device->Height; + if(Device->Height & 0x07) Device->Height = ((Device->Height >> 3) + 1) << 3; + + Device->FramebufferSize = Device->Width * Device->Height / 8; + Device->Framebuffer = calloc(1, Device->FramebufferSize); + NullCheck(Device->Framebuffer, return false); + + if(Private->ReadyPin >= 0) { + esp_rom_gpio_pad_select_gpio(Private->ReadyPin); + gpio_set_pull_mode(Private->ReadyPin, GPIO_PULLUP_ONLY); + gpio_set_direction(Private->ReadyPin, GPIO_MODE_INPUT); + } + + // soft reset + vTaskDelay(pdMS_TO_TICKS(2000)); + Device->WriteCommand(Device, 0x12); + WaitReady(Device); + + Device->WriteCommand(Device, 0x74); + WriteByte(Device, 0x54); + Device->WriteCommand(Device, 0x7e); + WriteByte(Device, 0x3B); + + Device->WriteCommand(Device, 0x3c); + WriteByte(Device, 0x03); + + Device->WriteCommand(Device, 0x2c); + WriteByte(Device, 0x55); + + Device->WriteCommand(Device, 0x03); + WriteByte(Device, EPD_lut_full_update[70]); + + Device->WriteCommand(Device, 0x04); + WriteByte(Device, EPD_lut_full_update[71]); + WriteByte(Device, EPD_lut_full_update[72]); + WriteByte(Device, EPD_lut_full_update[73]); + + Device->WriteCommand(Device, 0x3a); + WriteByte(Device, EPD_lut_full_update[74]); + Device->WriteCommand(Device, 0x3b); + WriteByte(Device, EPD_lut_full_update[75]); + + Device->WriteCommand(Device, 0X32); + for(int i = 0; i < 70; i++) { WriteByte(Device, EPD_lut_full_update[i]); } + + // now deal with funny X/Y layout (W and H are "inverted") + Device->WriteCommand(Device, 0x01); + WriteByte(Device, Device->Width - 1); + WriteByte(Device, (Device->Width - 1) >> 8); + WriteByte(Device, (0 << 0)); + + /* Start from 0, Ymax, incX, decY. Starting from X=Height would be difficult as we would hit the extra bits added because height % 8 != 0 and they are not written by the DrawPixel. By starting from X=0 we are aligned and doing incY is like a clockwise 90° rotation (vs otherwise we would virtually do a counter-clockwise rotation but again have the "border" issue. - */ - Device->WriteCommand( Device, 0x11 ); - WriteByte( Device, (1 << 2) | (0 << 1) | (1 << 0)); - - // must be in order with increment/decrement i.e start might be > end if we decrement - SetColumnAddress( Device, 0x0, (Device->Height >> 3) - 1 ); - SetRowAddress ( Device, Device->Width - 1, 0 ); + */ + Device->WriteCommand(Device, 0x11); + WriteByte(Device, (1 << 2) | (0 << 1) | (1 << 0)); - WaitReady( Device ); - - Update( Device ); - - return true; + // must be in order with increment/decrement i.e start might be > end if we decrement + SetColumnAddress(Device, 0x0, (Device->Height >> 3) - 1); + SetRowAddress(Device, Device->Width - 1, 0); + + WaitReady(Device); + + Update(Device); + + return true; } static const struct GDS_Device SSD1675 = { @@ -239,15 +358,13 @@ static const struct GDS_Device SSD1675 = { }; struct GDS_Device* SSD1675_Detect(sys_display_config* Driver, struct GDS_Device* Device) { - if (Driver->common.driver != sys_display_drivers_SSD1675) return NULL; + if(Driver->common.driver != sys_display_drivers_SSD1675) return NULL; - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); *Device = SSD1675; struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; Private->ReadyPin = -1; - if (Driver->common.ready >= 0) { - Private->ReadyPin = Driver->common.ready; - } + if(Driver->common.ready >= 0) { Private->ReadyPin = Driver->common.ready; } ESP_LOGI(TAG, "SSD1675 driver with ready GPIO %d", Private->ReadyPin); diff --git a/components/display/ST77xx.c b/components/display/ST77xx.c index 42260375..4ff33431 100644 --- a/components/display/ST77xx.c +++ b/components/display/ST77xx.c @@ -18,288 +18,301 @@ #define SHADOW_BUFFER #define USE_IRAM -#define PAGE_BLOCK 2048 -#define ENABLE_WRITE 0x2c +#define PAGE_BLOCK 2048 +#define ENABLE_WRITE 0x2c -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) static char TAG[] = "ST77xx"; enum { ST7735, ST7789 }; struct PrivateSpace { - uint8_t *iRAM, *Shadowbuffer; - struct { - uint16_t Height, Width; - } Offset; - uint8_t MADCtl, PageSize; - uint8_t Model; + uint8_t *iRAM, *Shadowbuffer; + struct { + uint16_t Height, Width; + } Offset; + uint8_t MADCtl, PageSize; + uint8_t Model; }; // Functions are not declared to minimize # of lines -static void WriteByte( struct GDS_Device* Device, uint8_t Data ) { - Device->WriteData( Device, &Data, 1 ); +static void WriteByte(struct GDS_Device* Device, uint8_t Data) { Device->WriteData(Device, &Data, 1); } + +static void SetColumnAddress(struct GDS_Device* Device, uint16_t Start, uint16_t End) { + uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); + Device->WriteCommand(Device, 0x2A); + Device->WriteData(Device, (uint8_t*)&Addr, 4); } -static void SetColumnAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) { - uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); - Device->WriteCommand( Device, 0x2A ); - Device->WriteData( Device, (uint8_t*) &Addr, 4 ); +static void SetRowAddress(struct GDS_Device* Device, uint16_t Start, uint16_t End) { + uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); + Device->WriteCommand(Device, 0x2B); + Device->WriteData(Device, (uint8_t*)&Addr, 4); } -static void SetRowAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) { - uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16); - Device->WriteCommand( Device, 0x2B ); - Device->WriteData( Device, (uint8_t*) &Addr, 4 ); -} +static void Update16(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; -static void Update16( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - #ifdef SHADOW_BUFFER - uint32_t *optr = (uint32_t*) Private->Shadowbuffer, *iptr = (uint32_t*) Device->Framebuffer; - int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - - for (int r = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width is always a multiple of 2) - for (int c = 0; c < Device->Width / 2; c++, iptr++, optr++) { - if (*optr != *iptr) { - *optr = *iptr; - if (c < FirstCol) FirstCol = c; - if (c > LastCol) LastCol = c; - if (FirstRow < 0) FirstRow = r; - LastRow = r; - } - } + uint32_t *optr = (uint32_t*)Private->Shadowbuffer, *iptr = (uint32_t*)Device->Framebuffer; + int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - // wait for a large enough window - careful that window size might increase by more than a line at once ! - if (FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; - - FirstCol *= 2; - LastCol = LastCol * 2 + 1; - SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); - SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width ); - Device->WriteCommand( Device, ENABLE_WRITE ); - - int ChunkSize = (LastCol - FirstCol + 1) * 2; - - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - uint8_t *optr = Private->iRAM; - for (int i = FirstRow; i <= LastRow; i++) { - memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); - optr += ChunkSize; - if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; - Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); - optr = Private->iRAM; - } - } else for (int i = FirstRow; i <= LastRow; i++) { - Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize ); - } + for(int r = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width is always a multiple of 2) + for(int c = 0; c < Device->Width / 2; c++, iptr++, optr++) { + if(*optr != *iptr) { + *optr = *iptr; + if(c < FirstCol) FirstCol = c; + if(c > LastCol) LastCol = c; + if(FirstRow < 0) FirstRow = r; + LastRow = r; + } + } - FirstCol = Device->Width / 2; LastCol = 0; - FirstRow = -1; - } + // wait for a large enough window - careful that window size might increase by more than a line at once ! + if(FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue; + + FirstCol *= 2; + LastCol = LastCol * 2 + 1; + SetRowAddress(Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); + SetColumnAddress(Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width); + Device->WriteCommand(Device, ENABLE_WRITE); + + int ChunkSize = (LastCol - FirstCol + 1) * 2; + + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + uint8_t* optr = Private->iRAM; + for(int i = FirstRow; i <= LastRow; i++) { + memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); + optr += ChunkSize; + if(optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; + Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); + optr = Private->iRAM; + } + } else + for(int i = FirstRow; i <= LastRow; i++) { + Device->WriteData(Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize); + } + + FirstCol = Device->Width / 2; + LastCol = 0; + FirstRow = -1; + } #else - // always update by full lines - SetColumnAddress( Device, Private->Offset.Width, Device->Width - 1); - - for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { - int Height = min(Private->PageSize, Device->Height - r); - - SetRowAddress( Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1 ); - Device->WriteCommand(Device, ENABLE_WRITE); - - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 ); - Device->WriteData( Device, Private->iRAM, Height * Device->Width * 2 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2 ); - } - } -#endif + // always update by full lines + SetColumnAddress(Device, Private->Offset.Width, Device->Width - 1); + + for(int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { + int Height = min(Private->PageSize, Device->Height - r); + + SetRowAddress(Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1); + Device->WriteCommand(Device, ENABLE_WRITE); + + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2); + Device->WriteData(Device, Private->iRAM, Height * Device->Width * 2); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width * 2, Height * Device->Width * 2); + } + } +#endif } -static void Update24( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - -#ifdef SHADOW_BUFFER - uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer; - int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0; - - for (int r = 0; r < Device->Height; r++) { - // look for change and update shadow (cheap optimization = width always / by 2) - for (int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) { - if (*optr != *iptr) { - *optr = *iptr; - if (c < FirstCol) FirstCol = c; - if (c > LastCol) LastCol = c; - if (FirstRow < 0) FirstRow = r; - LastRow = r; - } - } - - // do we have enough to send (cols are divided by 3/2) - if (FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2 + 3 - 1) / 3) * (r - FirstRow + 1) * 3 < PAGE_BLOCK && r != Device->Height - 1)) continue; - - FirstCol = (FirstCol * 2) / 3; - LastCol = (LastCol * 2 + 1) / 3; - SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); - SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width ); - Device->WriteCommand( Device, ENABLE_WRITE ); - - int ChunkSize = (LastCol - FirstCol + 1) * 3; - - // own use of IRAM has not proven to be much better than letting SPI do its copy - if (Private->iRAM) { - uint8_t *optr = Private->iRAM; - for (int i = FirstRow; i <= LastRow; i++) { - memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); - optr += ChunkSize; - if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; - Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); - optr = Private->iRAM; - } - } else for (int i = FirstRow; i <= LastRow; i++) { - Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize ); - } +static void Update24(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; - FirstCol = (Device->Width * 3) / 2; LastCol = 0; - FirstRow = -1; - } +#ifdef SHADOW_BUFFER + uint16_t *optr = (uint16_t*)Private->Shadowbuffer, *iptr = (uint16_t*)Device->Framebuffer; + int FirstCol = (Device->Width * 3) / 2, LastCol = 0, FirstRow = -1, LastRow = 0; + + for(int r = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width always / by 2) + for(int c = 0; c < (Device->Width * 3) / 2; c++, optr++, iptr++) { + if(*optr != *iptr) { + *optr = *iptr; + if(c < FirstCol) FirstCol = c; + if(c > LastCol) LastCol = c; + if(FirstRow < 0) FirstRow = r; + LastRow = r; + } + } + + // do we have enough to send (cols are divided by 3/2) + if(FirstRow < 0 || ((((LastCol - FirstCol + 1) * 2 + 3 - 1) / 3) * (r - FirstRow + 1) * 3 < PAGE_BLOCK && r != Device->Height - 1)) continue; + + FirstCol = (FirstCol * 2) / 3; + LastCol = (LastCol * 2 + 1) / 3; + SetRowAddress(Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height); + SetColumnAddress(Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width); + Device->WriteCommand(Device, ENABLE_WRITE); + + int ChunkSize = (LastCol - FirstCol + 1) * 3; + + // own use of IRAM has not proven to be much better than letting SPI do its copy + if(Private->iRAM) { + uint8_t* optr = Private->iRAM; + for(int i = FirstRow; i <= LastRow; i++) { + memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); + optr += ChunkSize; + if(optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue; + Device->WriteData(Device, Private->iRAM, optr - Private->iRAM); + optr = Private->iRAM; + } + } else + for(int i = FirstRow; i <= LastRow; i++) { + Device->WriteData(Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize); + } + + FirstCol = (Device->Width * 3) / 2; + LastCol = 0; + FirstRow = -1; + } #else - // always update by full lines - SetColumnAddress( Device, Private->Offset.Width, Device->Width - 1); - - for (int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { - int Height = min(Private->PageSize, Device->Height - r); - - SetRowAddress( Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1 ); - Device->WriteCommand(Device, ENABLE_WRITE); - - if (Private->iRAM) { - memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 ); - Device->WriteData( Device, Private->iRAM, Height * Device->Width * 3 ); - } else { - Device->WriteData( Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3 ); - } - } -#endif + // always update by full lines + SetColumnAddress(Device, Private->Offset.Width, Device->Width - 1); + + for(int r = 0; r < Device->Height; r += min(Private->PageSize, Device->Height - r)) { + int Height = min(Private->PageSize, Device->Height - r); + + SetRowAddress(Device, Private->Offset.Height + r, Private->Offset.Height + r + Height - 1); + Device->WriteCommand(Device, ENABLE_WRITE); + + if(Private->iRAM) { + memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3); + Device->WriteData(Device, Private->iRAM, Height * Device->Width * 3); + } else { + Device->WriteData(Device, Device->Framebuffer + r * Device->Width * 3, Height * Device->Width * 3); + } + } +#endif } -static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - - if (Private->Model == ST7789) { - if (Layout->Rotate) Private->Offset.Width += Layout->HFlip ? 320 - Device->Width : 0; - else Private->Offset.Height += Layout->HFlip ? 320 - Device->Height : 0; - Device->WriteCommand( Device, Layout->Invert ? 0x20 : 0x21 ); - } else { - Device->WriteCommand( Device, Layout->Invert ? 0x21 : 0x20 ); - } +static void SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; - Private->MADCtl = Layout->HFlip ? (Private->MADCtl | (1 << 7)) : (Private->MADCtl & ~(1 << 7)); - Private->MADCtl = Layout->VFlip ? (Private->MADCtl | (1 << 6)) : (Private->MADCtl & ~(1 << 6)); - Private->MADCtl = Layout->Rotate ? (Private->MADCtl | (1 << 5)) : (Private->MADCtl & ~(1 << 5)); - Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl & ~(1 << 3)) : (Private->MADCtl | (1 << 3)); + if(Private->Model == ST7789) { + if(Layout->Rotate) + Private->Offset.Width += Layout->HFlip ? 320 - Device->Width : 0; + else + Private->Offset.Height += Layout->HFlip ? 320 - Device->Height : 0; + Device->WriteCommand(Device, Layout->Invert ? 0x20 : 0x21); + } else { + Device->WriteCommand(Device, Layout->Invert ? 0x21 : 0x20); + } - Device->WriteCommand( Device, 0x36 ); - WriteByte( Device, Private->MADCtl ); + Private->MADCtl = Layout->HFlip ? (Private->MADCtl | (1 << 7)) : (Private->MADCtl & ~(1 << 7)); + Private->MADCtl = Layout->VFlip ? (Private->MADCtl | (1 << 6)) : (Private->MADCtl & ~(1 << 6)); + Private->MADCtl = Layout->Rotate ? (Private->MADCtl | (1 << 5)) : (Private->MADCtl & ~(1 << 5)); + Private->MADCtl = Layout->ColorSwap ? (Private->MADCtl & ~(1 << 3)) : (Private->MADCtl | (1 << 3)); + + Device->WriteCommand(Device, 0x36); + WriteByte(Device, Private->MADCtl); #ifdef SHADOW_BUFFER - // force a full refresh (almost ...) - memset(Private->Shadowbuffer, 0xAA, Device->FramebufferSize); -#endif -} - -static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0x29 ); } -static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0x28 ); } - -static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - Device->WriteCommand( Device, 0x51 ); - WriteByte( Device, Contrast ); - - Device->SetContrast = NULL; - GDS_SetContrast( Device, Contrast ); - Device->SetContrast = SetContrast; + // force a full refresh (almost ...) + memset(Private->Shadowbuffer, 0xAA, Device->FramebufferSize); +#endif } -static bool Init( struct GDS_Device* Device ) { - struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; - int Depth = (Device->Depth + 8 - 1) / 8; - - Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth)); +static void DisplayOn(struct GDS_Device* Device) { Device->WriteCommand(Device, 0x29); } +static void DisplayOff(struct GDS_Device* Device) { Device->WriteCommand(Device, 0x28); } -#ifdef SHADOW_BUFFER - Private->Shadowbuffer = malloc( Device->FramebufferSize ); - memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +static void SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + Device->WriteCommand(Device, 0x51); + WriteByte(Device, Contrast); + + Device->SetContrast = NULL; + GDS_SetContrast(Device, Contrast); + Device->SetContrast = SetContrast; +} + +static bool Init(struct GDS_Device* Device) { + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + int Depth = (Device->Depth + 8 - 1) / 8; + + Private->PageSize = min(8, PAGE_BLOCK / (Device->Width * Depth)); + +#ifdef SHADOW_BUFFER + Private->Shadowbuffer = malloc(Device->FramebufferSize); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); #endif #ifdef USE_IRAM - Private->iRAM = heap_caps_malloc( (Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); + Private->iRAM = heap_caps_malloc((Private->PageSize + 1) * Device->Width * Depth, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); #endif - ESP_LOGI(TAG, "ST77xx with bit depth %u, offsets %hu:%hu, page %u, iRAM %p", Device->Depth, Private->Offset.Height, Private->Offset.Width, Private->PageSize, Private->iRAM); - - // Sleepout + Booster - Device->WriteCommand( Device, 0x11 ); - - // need BGR & Address Mode - Private->MADCtl = 1 << 3; - Device->WriteCommand( Device, 0x36 ); - WriteByte( Device, Private->MADCtl ); - - // set flip modes & contrast - GDS_SetContrast( Device, 0x7f ); - struct GDS_Layout Layout = { }; - Device->SetLayout( Device, &Layout ); - - // set screen depth (16/18) - Device->WriteCommand( Device, 0x3A ); - if (Private->Model == ST7789) WriteByte( Device, Device->Depth == 24 ? 0x066 : 0x55 ); - else WriteByte( Device, Device->Depth == 24 ? 0x06 : 0x05 ); - - // gone with the wind - Device->DisplayOn( Device ); - Device->Update( Device ); + ESP_LOGI(TAG, "ST77xx with bit depth %u, offsets %hu:%hu, page %u, iRAM %p", Device->Depth, Private->Offset.Height, Private->Offset.Width, + Private->PageSize, Private->iRAM); - return true; -} + // Sleepout + Booster + Device->WriteCommand(Device, 0x11); + + // need BGR & Address Mode + Private->MADCtl = 1 << 3; + Device->WriteCommand(Device, 0x36); + WriteByte(Device, Private->MADCtl); + + // set flip modes & contrast + GDS_SetContrast(Device, 0x7f); + struct GDS_Layout Layout = {}; + Device->SetLayout(Device, &Layout); + + // set screen depth (16/18) + Device->WriteCommand(Device, 0x3A); + if(Private->Model == ST7789) + WriteByte(Device, Device->Depth == 24 ? 0x066 : 0x55); + else + WriteByte(Device, Device->Depth == 24 ? 0x06 : 0x05); + + // gone with the wind + Device->DisplayOn(Device); + Device->Update(Device); + + return true; +} static const struct GDS_Device ST77xx = { - .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, - .SetLayout = SetLayout, - .Update = Update16, .Init = Init, - .Mode = GDS_RGB565, .Depth = 16, -}; + .DisplayOn = DisplayOn, + .DisplayOff = DisplayOff, + .SetLayout = SetLayout, + .Update = Update16, + .Init = Init, + .Mode = GDS_RGB565, + .Depth = 16, +}; -struct GDS_Device* ST77xx_Detect(sys_display_config * Driver, struct GDS_Device* Device) { - uint8_t Model; - int Depth; - if(Driver->common.driver == sys_display_drivers_ST7735) Model = ST7735; - else if(Driver->common.driver == sys_display_drivers_ST7789) Model = ST7789; - else return NULL; - - if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); - - *Device = ST77xx; - Depth = Driver->common.bitDepth != 0?Driver->common.bitDepth:18; +struct GDS_Device* ST77xx_Detect(sys_display_config* Driver, struct GDS_Device* Device) { + uint8_t Model; + int Depth; + if(Driver->common.driver == sys_display_drivers_ST7735) + Model = ST7735; + else if(Driver->common.driver == sys_display_drivers_ST7789) + Model = ST7789; + else + return NULL; - struct PrivateSpace* Private = (struct PrivateSpace*) Device->Private; - Private->Model = Model; + if(!Device) Device = calloc(1, sizeof(struct GDS_Device)); - if(Driver->common.has_offsets){ - Private->Offset.Height = Driver->common.offsets.height; - Private->Offset.Width = Driver->common.offsets.width; - } - - if (Depth == 18) { - Device->Mode = GDS_RGB666; - Device->Depth = 24; - Device->Update = Update24; - } - - if (Model == ST7789) Device->SetContrast = SetContrast; + *Device = ST77xx; + Depth = Driver->common.bitDepth != 0 ? Driver->common.bitDepth : 18; - return Device; + struct PrivateSpace* Private = (struct PrivateSpace*)Device->Private; + Private->Model = Model; + + if(Driver->common.has_offsets) { + Private->Offset.Height = Driver->common.offsets.height; + Private->Offset.Width = Driver->common.offsets.width; + } + + if(Depth == 18) { + Device->Mode = GDS_RGB666; + Device->Depth = 24; + Device->Update = Update24; + } + + if(Model == ST7789) Device->SetContrast = SetContrast; + + return Device; } \ No newline at end of file diff --git a/components/display/core/gds.c b/components/display/core/gds.c index 4ebe6477..3f6eae08 100644 --- a/components/display/core/gds.c +++ b/components/display/core/gds.c @@ -23,235 +23,251 @@ #define LEDC_SPEED_MODE LEDC_LOW_SPEED_MODE #else #define LEDC_SPEED_MODE LEDC_HIGH_SPEED_MODE -#endif +#endif extern bool gds_init_fonts(); static struct GDS_Device Display; static struct GDS_BacklightPWM PWMConfig; static char TAG[] = "gds"; -struct GDS_Device* GDS_AutoDetect( sys_display_config * Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM* PWM ) { - if (!Driver->has_common || Driver->common.driver == sys_display_drivers_UNSPECIFIED) return NULL; - if (PWM) PWMConfig = *PWM; - - for (int i = 0; DetectFunc[i]; i++) { - if (DetectFunc[i](Driver, &Display)) { - if (PWM && PWM->Init) { - ledc_timer_config_t PWMTimer = { - .duty_resolution = LEDC_TIMER_13_BIT, - .freq_hz = 5000, - .speed_mode = LEDC_SPEED_MODE, - .timer_num = PWMConfig.Timer, - }; - ledc_timer_config(&PWMTimer); - } - ESP_LOGD(TAG, "Detected driver %p with PWM %d", &Display, PWM ? PWM->Init : 0); - return &Display; - } - } - - return NULL; +struct GDS_Device* GDS_AutoDetect(sys_display_config* Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM* PWM) { + if(!Driver->has_common || Driver->common.driver == sys_display_drivers_UNSPECIFIED) return NULL; + if(PWM) PWMConfig = *PWM; + + for(int i = 0; DetectFunc[i]; i++) { + if(DetectFunc[i](Driver, &Display)) { + if(PWM && PWM->Init) { + ledc_timer_config_t PWMTimer = { + .duty_resolution = LEDC_TIMER_13_BIT, + .freq_hz = 5000, + .speed_mode = LEDC_SPEED_MODE, + .timer_num = PWMConfig.Timer, + }; + ledc_timer_config(&PWMTimer); + } + ESP_LOGD(TAG, "Detected driver %p with PWM %d", &Display, PWM ? PWM->Init : 0); + return &Display; + } + } + + return NULL; } void GDS_ClearExt(struct GDS_Device* Device, bool full, ...) { - bool commit = true; - - if (full) { - GDS_Clear( Device, GDS_COLOR_BLACK ); - } else { - va_list args; - va_start(args, full); - commit = va_arg(args, int); - int x1 = va_arg(args, int), y1 = va_arg(args, int), x2 = va_arg(args, int), y2 = va_arg(args, int); - if (x2 < 0) x2 = Device->Width - 1; - if (y2 < 0) y2 = Device->Height - 1; - GDS_ClearWindow( Device, x1, y1, x2, y2, GDS_COLOR_BLACK ); - va_end(args); - } - - Device->Dirty = true; - if (commit) GDS_Update(Device); -} + bool commit = true; -void GDS_Clear( struct GDS_Device* Device, int Color ) { - if (Color == GDS_COLOR_BLACK) memset( Device->Framebuffer, 0, Device->FramebufferSize ); - else if (Device->Depth == 1) memset( Device->Framebuffer, 0xff, Device->FramebufferSize ); - else if (Device->Depth == 4) memset( Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize ); - else if (Device->Depth == 8) memset( Device->Framebuffer, Color, Device->FramebufferSize ); - else GDS_ClearWindow(Device, 0, 0, -1, -1, Color); - Device->Dirty = true; + if(full) { + GDS_Clear(Device, GDS_COLOR_BLACK); + } else { + va_list args; + va_start(args, full); + commit = va_arg(args, int); + int x1 = va_arg(args, int), y1 = va_arg(args, int), x2 = va_arg(args, int), y2 = va_arg(args, int); + if(x2 < 0) x2 = Device->Width - 1; + if(y2 < 0) y2 = Device->Height - 1; + GDS_ClearWindow(Device, x1, y1, x2, y2, GDS_COLOR_BLACK); + va_end(args); + } + + Device->Dirty = true; + if(commit) GDS_Update(Device); } -#define CLEAR_WINDOW(x1,y1,x2,y2,F,W,C,T,N) \ - for (int y = y1; y <= y2; y++) { \ - T *Ptr = (T*) F + (y * W + x1)*N; \ - for (int c = (x2 - x1)*N; c-- >= 0; *Ptr++ = C); \ - } - -void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) { - // -1 means up to width/height - if (x2 < 0) x2 = Device->Width - 1; - if (y2 < 0) y2 = Device->Height - 1; - - // driver can provide own optimized clear window - if (Device->ClearWindow) { - Device->ClearWindow( Device, x1, y1, x2, y2, Color ); - } else if (Device->Depth == 1) { - // single shot if we erase all screen - if (x2 - x1 == Device->Width - 1 && y2 - y1 == Device->Height - 1) { - memset( Device->Framebuffer, Color == GDS_COLOR_BLACK ? 0 : 0xff, Device->FramebufferSize ); - } else { - uint8_t _Color = Color == GDS_COLOR_BLACK ? 0: 0xff; - uint8_t Width = Device->Width >> 3; - uint8_t *optr = Device->Framebuffer; - // try to do byte processing as much as possible - for (int r = y1; r <= y2;) { - int c = x1; - // for a row that is not on a boundary, no optimization possible - while (r & 0x07 && r <= y2) { - for (c = x1; c <= x2; c++) DrawPixelFast( Device, c, r, Color ); - r++; - } - // go fast if we have more than 8 lines to write - if (r + 8 <= y2) { - memset(optr + Width * r + x1, _Color, x2 - x1 + 1); - r += 8; - } else while (r <= y2) { - for (c = x1; c <= x2; c++) DrawPixelFast( Device, c, r, Color ); - r++; - } - } - } - } if (Device->Depth == 4) { - if (x2 - x1 == Device->Width - 1 && y2 - y1 == Device->Height - 1) { - // we assume color is 0..15 - memset( Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize ); - } else { - uint8_t _Color = Color | (Color << 4); - int Width = Device->Width; - uint8_t *optr = Device->Framebuffer; - // try to do byte processing as much as possible - for (int r = y1; r <= y2; r++) { - int c = x1; - if (c & 0x01) DrawPixelFast( Device, c++, r, Color); - int chunk = (x2 - c + 1) >> 1; - memset(optr + ((r * Width + c) >> 1), _Color, chunk); - if (c + chunk <= x2) DrawPixelFast( Device, x2, r, Color); - } - } - } else if (Device->Depth == 8) { - CLEAR_WINDOW(x1,y1,x2,y2,Device->Framebuffer,Device->Width,Color,uint8_t,1); - } else if (Device->Depth == 16) { - CLEAR_WINDOW(x1,y1,x2,y2,Device->Framebuffer,Device->Width,Color,uint16_t,1); - } else if (Device->Depth == 24) { - CLEAR_WINDOW(x1,y1,x2,y2,Device->Framebuffer,Device->Width,Color,uint8_t,3); - } else { - for (int y = y1; y <= y2; y++) { - for (int x = x1; x <= x2; x++) { - DrawPixelFast( Device, x, y, Color); - } - } - } - - // make sure diplay will do update - Device->Dirty = true; +void GDS_Clear(struct GDS_Device* Device, int Color) { + if(Color == GDS_COLOR_BLACK) + memset(Device->Framebuffer, 0, Device->FramebufferSize); + else if(Device->Depth == 1) + memset(Device->Framebuffer, 0xff, Device->FramebufferSize); + else if(Device->Depth == 4) + memset(Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize); + else if(Device->Depth == 8) + memset(Device->Framebuffer, Color, Device->FramebufferSize); + else + GDS_ClearWindow(Device, 0, 0, -1, -1, Color); + Device->Dirty = true; } -void GDS_Update( struct GDS_Device* Device ) { - if (Device->Dirty) Device->Update( Device ); - Device->Dirty = false; +#define CLEAR_WINDOW(x1, y1, x2, y2, F, W, C, T, N) \ + for(int y = y1; y <= y2; y++) { \ + T* Ptr = (T*)F + (y * W + x1) * N; \ + for(int c = (x2 - x1) * N; c-- >= 0; *Ptr++ = C); \ + } + +void GDS_ClearWindow(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color) { + // -1 means up to width/height + if(x2 < 0) x2 = Device->Width - 1; + if(y2 < 0) y2 = Device->Height - 1; + + // driver can provide own optimized clear window + if(Device->ClearWindow) { + Device->ClearWindow(Device, x1, y1, x2, y2, Color); + } else if(Device->Depth == 1) { + // single shot if we erase all screen + if(x2 - x1 == Device->Width - 1 && y2 - y1 == Device->Height - 1) { + memset(Device->Framebuffer, Color == GDS_COLOR_BLACK ? 0 : 0xff, Device->FramebufferSize); + } else { + uint8_t _Color = Color == GDS_COLOR_BLACK ? 0 : 0xff; + uint8_t Width = Device->Width >> 3; + uint8_t* optr = Device->Framebuffer; + // try to do byte processing as much as possible + for(int r = y1; r <= y2;) { + int c = x1; + // for a row that is not on a boundary, no optimization possible + while(r & 0x07 && r <= y2) { + for(c = x1; c <= x2; c++) DrawPixelFast(Device, c, r, Color); + r++; + } + // go fast if we have more than 8 lines to write + if(r + 8 <= y2) { + memset(optr + Width * r + x1, _Color, x2 - x1 + 1); + r += 8; + } else + while(r <= y2) { + for(c = x1; c <= x2; c++) DrawPixelFast(Device, c, r, Color); + r++; + } + } + } + } + if(Device->Depth == 4) { + if(x2 - x1 == Device->Width - 1 && y2 - y1 == Device->Height - 1) { + // we assume color is 0..15 + memset(Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize); + } else { + uint8_t _Color = Color | (Color << 4); + int Width = Device->Width; + uint8_t* optr = Device->Framebuffer; + // try to do byte processing as much as possible + for(int r = y1; r <= y2; r++) { + int c = x1; + if(c & 0x01) DrawPixelFast(Device, c++, r, Color); + int chunk = (x2 - c + 1) >> 1; + memset(optr + ((r * Width + c) >> 1), _Color, chunk); + if(c + chunk <= x2) DrawPixelFast(Device, x2, r, Color); + } + } + } else if(Device->Depth == 8) { + CLEAR_WINDOW(x1, y1, x2, y2, Device->Framebuffer, Device->Width, Color, uint8_t, 1); + } else if(Device->Depth == 16) { + CLEAR_WINDOW(x1, y1, x2, y2, Device->Framebuffer, Device->Width, Color, uint16_t, 1); + } else if(Device->Depth == 24) { + CLEAR_WINDOW(x1, y1, x2, y2, Device->Framebuffer, Device->Width, Color, uint8_t, 3); + } else { + for(int y = y1; y <= y2; y++) { + for(int x = x1; x <= x2; x++) { DrawPixelFast(Device, x, y, Color); } + } + } + + // make sure diplay will do update + Device->Dirty = true; } -bool GDS_Reset( struct GDS_Device* Device ) { - if ( Device->RSTPin >= 0 ) { - gpio_set_level( Device->RSTPin, 0 ); - vTaskDelay( pdMS_TO_TICKS( 100 ) ); - gpio_set_level( Device->RSTPin, 1 ); +void GDS_Update(struct GDS_Device* Device) { + if(Device->Dirty) Device->Update(Device); + Device->Dirty = false; +} + +bool GDS_Reset(struct GDS_Device* Device) { + if(Device->RSTPin >= 0) { + gpio_set_level(Device->RSTPin, 0); + vTaskDelay(pdMS_TO_TICKS(100)); + gpio_set_level(Device->RSTPin, 1); } return true; } -bool GDS_Init( struct GDS_Device* Device ) { - - if (Device->Depth > 8) Device->FramebufferSize = Device->Width * Device->Height * ((8 + Device->Depth - 1) / 8); - else Device->FramebufferSize = (Device->Width * Device->Height) / (8 / Device->Depth); - - // allocate FB unless explicitely asked not to - if (!(Device->Alloc & GDS_ALLOC_NONE)) { - if ((Device->Alloc & GDS_ALLOC_IRAM) || ((Device->Alloc & GDS_ALLOC_IRAM_SPI) && Device->IF == GDS_IF_SPI)) { - Device->Framebuffer = heap_caps_calloc( 1, Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); - } else { - Device->Framebuffer = calloc( 1, Device->FramebufferSize ); - } - NullCheck( Device->Framebuffer, return false ); - } - - if (Device->Backlight.Pin >= 0) { - Device->Backlight.Channel = PWMConfig.Channel++; - Device->Backlight.PWM = PWMConfig.Max - 1; +bool GDS_Init(struct GDS_Device* Device) { - ledc_channel_config_t PWMChannel = { - .channel = Device->Backlight.Channel, - .duty = Device->Backlight.PWM, - .gpio_num = Device->Backlight.Pin, + if(Device->Depth > 8) + Device->FramebufferSize = Device->Width * Device->Height * ((8 + Device->Depth - 1) / 8); + else + Device->FramebufferSize = (Device->Width * Device->Height) / (8 / Device->Depth); + + // allocate FB unless explicitely asked not to + if(!(Device->Alloc & GDS_ALLOC_NONE)) { + if((Device->Alloc & GDS_ALLOC_IRAM) || ((Device->Alloc & GDS_ALLOC_IRAM_SPI) && Device->IF == GDS_IF_SPI)) { + Device->Framebuffer = heap_caps_calloc(1, Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + } else { + Device->Framebuffer = calloc(1, Device->FramebufferSize); + } + NullCheck(Device->Framebuffer, return false); + } + + if(Device->Backlight.Pin >= 0) { + Device->Backlight.Channel = PWMConfig.Channel++; + Device->Backlight.PWM = PWMConfig.Max - 1; + + ledc_channel_config_t PWMChannel = { + .channel = Device->Backlight.Channel, + .duty = Device->Backlight.PWM, + .gpio_num = Device->Backlight.Pin, .speed_mode = LEDC_SPEED_MODE, - .hpoint = 0, - .timer_sel = PWMConfig.Timer, + .hpoint = 0, + .timer_sel = PWMConfig.Timer, }; - - ledc_channel_config(&PWMChannel); - } - - bool Res = Device->Init( Device ); - if(Res){ - Res = gds_init_fonts(); - } - if (!Res && Device->Framebuffer) free(Device->Framebuffer); - - return Res; + + ledc_channel_config(&PWMChannel); + } + + bool Res = Device->Init(Device); + if(Res) { Res = gds_init_fonts(); } + if(!Res && Device->Framebuffer) free(Device->Framebuffer); + + return Res; } -int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level) { - switch(Device->Mode) { - case GDS_MONO: return Level; - case GDS_GRAYSCALE: return Level >> (8 - Device->Depth); - case GDS_RGB332: - Level >>= 5; - return (Level << 6) | (Level << 3) | (Level >> 1); - case GDS_RGB444: - Level >>= 4; - return (Level << 8) | (Level << 4) | Level; - case GDS_RGB555: - Level >>= 3; - return (Level << 10) | (Level << 5) | Level; - case GDS_RGB565: - Level >>= 2; - return ((Level & ~0x01) << 10) | (Level << 5) | (Level >> 1); - case GDS_RGB666: - Level >>= 2; - return (Level << 12) | (Level << 6) | Level; - case GDS_RGB888: - return (Level << 16) | (Level << 8) | Level; - } - - return -1; +int GDS_GrayMap(struct GDS_Device* Device, uint8_t Level) { + switch(Device->Mode) { + case GDS_MONO: + return Level; + case GDS_GRAYSCALE: + return Level >> (8 - Device->Depth); + case GDS_RGB332: + Level >>= 5; + return (Level << 6) | (Level << 3) | (Level >> 1); + case GDS_RGB444: + Level >>= 4; + return (Level << 8) | (Level << 4) | Level; + case GDS_RGB555: + Level >>= 3; + return (Level << 10) | (Level << 5) | Level; + case GDS_RGB565: + Level >>= 2; + return ((Level & ~0x01) << 10) | (Level << 5) | (Level >> 1); + case GDS_RGB666: + Level >>= 2; + return (Level << 12) | (Level << 6) | Level; + case GDS_RGB888: + return (Level << 16) | (Level << 8) | Level; + } + + return -1; } -void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { - if (Device->SetContrast) Device->SetContrast( Device, Contrast ); - else if (Device->Backlight.Pin >= 0) { - Device->Backlight.PWM = PWMConfig.Max * powf(Contrast / 255.0, 3); - ledc_set_duty( LEDC_SPEED_MODE, Device->Backlight.Channel, Device->Backlight.PWM ); - ledc_update_duty( LEDC_SPEED_MODE, Device->Backlight.Channel ); - } +void GDS_SetContrast(struct GDS_Device* Device, uint8_t Contrast) { + if(Device->SetContrast) + Device->SetContrast(Device, Contrast); + else if(Device->Backlight.Pin >= 0) { + Device->Backlight.PWM = PWMConfig.Max * powf(Contrast / 255.0, 3); + ledc_set_duty(LEDC_SPEED_MODE, Device->Backlight.Channel, Device->Backlight.PWM); + ledc_update_duty(LEDC_SPEED_MODE, Device->Backlight.Channel); + } } -void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { if (Device->SetLayout) Device->SetLayout( Device, Layout ); } -void GDS_SetDirty( struct GDS_Device* Device ) { Device->Dirty = true; } -int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; } -void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; } -int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; } -int GDS_GetDepth( struct GDS_Device* Device ) { return Device ? Device->Depth : 0; } -int GDS_GetMode( struct GDS_Device* Device ) { return Device ? Device->Mode : 0; } -void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device->DisplayOn) Device->DisplayOn( Device ); } -void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); } \ No newline at end of file +void GDS_SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout) { + if(Device->SetLayout) Device->SetLayout(Device, Layout); +} +void GDS_SetDirty(struct GDS_Device* Device) { Device->Dirty = true; } +int GDS_GetWidth(struct GDS_Device* Device) { return Device ? Device->Width : 0; } +void GDS_SetTextWidth(struct GDS_Device* Device, int TextWidth) { + Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; +} +int GDS_GetHeight(struct GDS_Device* Device) { return Device ? Device->Height : 0; } +int GDS_GetDepth(struct GDS_Device* Device) { return Device ? Device->Depth : 0; } +int GDS_GetMode(struct GDS_Device* Device) { return Device ? Device->Mode : 0; } +void GDS_DisplayOn(struct GDS_Device* Device) { + if(Device->DisplayOn) Device->DisplayOn(Device); +} +void GDS_DisplayOff(struct GDS_Device* Device) { + if(Device->DisplayOff) Device->DisplayOff(Device); +} \ No newline at end of file diff --git a/components/display/core/gds.h b/components/display/core/gds.h index fdac295a..4164d82a 100644 --- a/components/display/core/gds.h +++ b/components/display/core/gds.h @@ -12,46 +12,46 @@ other depth, you must supply the DrawPixelFast. The built-in 1 bit depth function are only for screen with vertical framing (1 byte = 8 lines). For example SSD1326 in monochrome mode is not such type of screen, SH1106 and SSD1306 are -*/ +*/ // this is an ordered enum, do not change! enum { GDS_MONO = 0, GDS_GRAYSCALE, GDS_RGB332, GDS_RGB444, GDS_RGB555, GDS_RGB565, GDS_RGB666, GDS_RGB888 }; - + #define GDS_COLOR_BLACK (0) #define GDS_COLOR_WHITE (-1) -#define GDS_COLOR_XOR (256) +#define GDS_COLOR_XOR (256) struct GDS_Device; struct GDS_FontDef; -struct GDS_BacklightPWM { - int Channel, Timer, Max; - bool Init; +struct GDS_BacklightPWM { + int Channel, Timer, Max; + bool Init; }; struct GDS_Layout { - bool HFlip, VFlip; - bool Rotate; - bool Invert; - bool ColorSwap; + bool HFlip, VFlip; + bool Rotate; + bool Invert; + bool ColorSwap; }; -typedef struct GDS_Device* GDS_DetectFunc(sys_display_config * Driver, struct GDS_Device *Device); +typedef struct GDS_Device* GDS_DetectFunc(sys_display_config* Driver, struct GDS_Device* Device); -struct GDS_Device* GDS_AutoDetect( sys_display_config * Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM *PWM ); +struct GDS_Device* GDS_AutoDetect(sys_display_config* Driver, GDS_DetectFunc* DetectFunc[], struct GDS_BacklightPWM* PWM); -void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ); -void GDS_DisplayOn( struct GDS_Device* Device ); -void GDS_DisplayOff( struct GDS_Device* Device ); -void GDS_Update( struct GDS_Device* Device ); -void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout* Layout); -void GDS_SetDirty( struct GDS_Device* Device ); -int GDS_GetWidth( struct GDS_Device* Device ); -void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ); -int GDS_GetHeight( struct GDS_Device* Device ); -int GDS_GetDepth( struct GDS_Device* Device ); -int GDS_GetMode( struct GDS_Device* Device ); -int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level ); -void GDS_ClearExt( struct GDS_Device* Device, bool full, ...); -void GDS_Clear( struct GDS_Device* Device, int Color ); -void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ); +void GDS_SetContrast(struct GDS_Device* Device, uint8_t Contrast); +void GDS_DisplayOn(struct GDS_Device* Device); +void GDS_DisplayOff(struct GDS_Device* Device); +void GDS_Update(struct GDS_Device* Device); +void GDS_SetLayout(struct GDS_Device* Device, struct GDS_Layout* Layout); +void GDS_SetDirty(struct GDS_Device* Device); +int GDS_GetWidth(struct GDS_Device* Device); +void GDS_SetTextWidth(struct GDS_Device* Device, int TextWidth); +int GDS_GetHeight(struct GDS_Device* Device); +int GDS_GetDepth(struct GDS_Device* Device); +int GDS_GetMode(struct GDS_Device* Device); +int GDS_GrayMap(struct GDS_Device* Device, uint8_t Level); +void GDS_ClearExt(struct GDS_Device* Device, bool full, ...); +void GDS_Clear(struct GDS_Device* Device, int Color); +void GDS_ClearWindow(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color); #endif diff --git a/components/display/core/gds_default_if.h b/components/display/core/gds_default_if.h index a657d17e..0280242e 100644 --- a/components/display/core/gds_default_if.h +++ b/components/display/core/gds_default_if.h @@ -7,11 +7,11 @@ extern "C" { struct GDS_Device; -bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int speed ); -bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin, int BacklightPin ); +bool GDS_I2CInit(int PortNumber, int SDA, int SCL, int speed); +bool GDS_I2CAttachDevice(struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin, int BacklightPin); -bool GDS_SPIInit( int SPI, int DC ); -bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin, int Mode ); +bool GDS_SPIInit(int SPI, int DC); +bool GDS_SPIAttachDevice(struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin, int Mode); #ifdef __cplusplus } diff --git a/components/display/core/gds_draw.c b/components/display/core/gds_draw.c index 3e3947ea..99f7c164 100644 --- a/components/display/core/gds_draw.c +++ b/components/display/core/gds_draw.c @@ -17,320 +17,409 @@ #include "gds.h" #include "gds_draw.h" -static const unsigned char BitReverseTable256[] = -{ - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; +static const unsigned char BitReverseTable256[] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; -__attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b ) { +__attribute__((always_inline)) static inline void SwapInt(int* a, int* b) { int Temp = *b; *b = *a; *a = Temp; } -void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) { - DrawPixelFast( Device, X, Y, Color ); -} +void IRAM_ATTR GDS_DrawPixelFast(struct GDS_Device* Device, int X, int Y, int Color) { DrawPixelFast(Device, X, Y, Color); } -void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int X, int Y, int Color ) { - DrawPixel( Device, X, Y, Color ); -} +void IRAM_ATTR GDS_DrawPixel(struct GDS_Device* Device, int X, int Y, int Color) { DrawPixel(Device, X, Y, Color); } -void GDS_DrawHLine( struct GDS_Device* Device, int x, int y, int Width, int Color ) { +void GDS_DrawHLine(struct GDS_Device* Device, int x, int y, int Width, int Color) { int XEnd = x + Width; - Device->Dirty = true; - - if (x < 0) x = 0; - if (XEnd >= Device->Width) XEnd = Device->Width - 1; - - if (y < 0) y = 0; - else if (y >= Device->Height) y = Device->Height - 1; + Device->Dirty = true; - for ( ; x < XEnd; x++ ) DrawPixelFast( Device, x, y, Color ); + if(x < 0) x = 0; + if(XEnd >= Device->Width) XEnd = Device->Width - 1; + + if(y < 0) + y = 0; + else if(y >= Device->Height) + y = Device->Height - 1; + + for(; x < XEnd; x++) DrawPixelFast(Device, x, y, Color); } -void GDS_DrawVLine( struct GDS_Device* Device, int x, int y, int Height, int Color ) { +void GDS_DrawVLine(struct GDS_Device* Device, int x, int y, int Height, int Color) { int YEnd = y + Height; - Device->Dirty = true; - - if (x < 0) x = 0; - if (x >= Device->Width) x = Device->Width - 1; - - if (y < 0) y = 0; - else if (YEnd >= Device->Height) YEnd = Device->Height - 1; + Device->Dirty = true; - for ( ; y < YEnd; y++ ) DrawPixel( Device, x, y, Color ); + if(x < 0) x = 0; + if(x >= Device->Width) x = Device->Width - 1; + + if(y < 0) + y = 0; + else if(YEnd >= Device->Height) + YEnd = Device->Height - 1; + + for(; y < YEnd; y++) DrawPixel(Device, x, y, Color); } -static inline void DrawWideLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ) { - int dx = ( x1 - x0 ); - int dy = ( y1 - y0 ); +static inline void DrawWideLine(struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color) { + int dx = (x1 - x0); + int dy = (y1 - y0); int Error = 0; int Incr = 1; int x = x0; int y = y0; - if ( dy < 0 ) { + if(dy < 0) { Incr = -1; dy = -dy; } - Error = ( dy * 2 ) - dx; + Error = (dy * 2) - dx; - for ( ; x < x1; x++ ) { - if ( IsPixelVisible( Device, x, y ) == true ) { - DrawPixelFast( Device, x, y, Color ); + for(; x < x1; x++) { + if(IsPixelVisible(Device, x, y) == true) { DrawPixelFast(Device, x, y, Color); } + + if(Error > 0) { + Error -= (dx * 2); + y += Incr; } - if ( Error > 0 ) { - Error-= ( dx * 2 ); - y+= Incr; - } - - Error+= ( dy * 2 ); + Error += (dy * 2); } } -static inline void DrawTallLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ) { - int dx = ( x1 - x0 ); - int dy = ( y1 - y0 ); +static inline void DrawTallLine(struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color) { + int dx = (x1 - x0); + int dy = (y1 - y0); int Error = 0; int Incr = 1; int x = x0; int y = y0; - if ( dx < 0 ) { + if(dx < 0) { Incr = -1; dx = -dx; } - Error = ( dx * 2 ) - dy; + Error = (dx * 2) - dy; - for ( ; y < y1; y++ ) { - if ( IsPixelVisible( Device, x, y ) == true ) { - DrawPixelFast( Device, x, y, Color ); + for(; y < y1; y++) { + if(IsPixelVisible(Device, x, y) == true) { DrawPixelFast(Device, x, y, Color); } + + if(Error > 0) { + Error -= (dy * 2); + x += Incr; } - if ( Error > 0 ) { - Error-= ( dy * 2 ); - x+= Incr; - } - - Error+= ( dx * 2 ); + Error += (dx * 2); } } -void GDS_DrawLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ) { - if ( x0 == x1 ) { - GDS_DrawVLine( Device, x0, y0, ( y1 - y0 ), Color ); - } else if ( y0 == y1 ) { - GDS_DrawHLine( Device, x0, y0, ( x1 - x0 ), Color ); +void GDS_DrawLine(struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color) { + if(x0 == x1) { + GDS_DrawVLine(Device, x0, y0, (y1 - y0), Color); + } else if(y0 == y1) { + GDS_DrawHLine(Device, x0, y0, (x1 - x0), Color); } else { - Device->Dirty = true; - if ( abs( x1 - x0 ) > abs( y1 - y0 ) ) { + Device->Dirty = true; + if(abs(x1 - x0) > abs(y1 - y0)) { /* Wide ( run > rise ) */ - if ( x0 > x1 ) { - SwapInt( &x0, &x1 ); - SwapInt( &y0, &y1 ); + if(x0 > x1) { + SwapInt(&x0, &x1); + SwapInt(&y0, &y1); } - DrawWideLine( Device, x0, y0, x1, y1, Color ); + DrawWideLine(Device, x0, y0, x1, y1, Color); } else { /* Tall ( rise > run ) */ - if ( y0 > y1 ) { - SwapInt( &y0, &y1 ); - SwapInt( &x0, &x1 ); + if(y0 > y1) { + SwapInt(&y0, &y1); + SwapInt(&x0, &x1); } - DrawTallLine( Device, x0, y0, x1, y1, Color ); + DrawTallLine(Device, x0, y0, x1, y1, Color); } } } -void GDS_DrawBox( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color, bool Fill ) { - int Width = ( x2 - x1 ); - int Height = ( y2 - y1 ); +void GDS_DrawBox(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color, bool Fill) { + int Width = (x2 - x1); + int Height = (y2 - y1); - Device->Dirty = true; - - if ( Fill == false ) { + Device->Dirty = true; + + if(Fill == false) { /* Top side */ - GDS_DrawHLine( Device, x1, y1, Width, Color ); + GDS_DrawHLine(Device, x1, y1, Width, Color); /* Bottom side */ - GDS_DrawHLine( Device, x1, y1 + Height, Width, Color ); + GDS_DrawHLine(Device, x1, y1 + Height, Width, Color); /* Left side */ - GDS_DrawVLine( Device, x1, y1, Height, Color ); + GDS_DrawVLine(Device, x1, y1, Height, Color); /* Right side */ - GDS_DrawVLine( Device, x1 + Width, y1, Height, Color ); + GDS_DrawVLine(Device, x1 + Width, y1, Height, Color); } else { /* Fill the box by drawing horizontal lines */ - for ( ; y1 <= y2; y1++ ) { - GDS_DrawHLine( Device, x1, y1, Width, Color ); - } + for(; y1 <= y2; y1++) { GDS_DrawHLine(Device, x1, y1, Width, Color); } } } - /**************************************************************************************** * Process graphic display data from column-oriented data (MSbit first) */ -void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) { - if (!Height) Height = Device->Height; - if (!Width) Width = Device->Width; - - if (Device->DrawBitmapCBR) { - Device->DrawBitmapCBR( Device, Data, Width, Height, Color ); - } else if (Device->Depth == 1) { - - Height >>= 3; - - // need to do row/col swap and bit-reverse - for (int r = 0; r < Height; r++) { - uint8_t *optr = Device->Framebuffer + r*Device->Width, *iptr = Data + r; - for (int c = Width; --c >= 0;) { - *optr++ = BitReverseTable256[*iptr]; - iptr += Height; - } - } - } else if (Device->Depth == 4) { - uint8_t *optr = Device->Framebuffer; - int LineLen = Device->Width >> 1; - - Height >>= 3; - Color &= 0x0f; - - for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { - uint8_t Byte = BitReverseTable256[*Data++]; - // we need to linearize code to let compiler better optimize - if (c & 0x01) { - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; - } else { - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; - } - // end of a column, move to next one - if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + (c >> 1); } - } - } else if (Device->Depth == 8) { - uint8_t *optr = Device->Framebuffer; - int LineLen = Device->Width; - - Height >>= 3; - - for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { - uint8_t Byte = BitReverseTable256[*Data++]; - - // we need to linearize code to let compiler better optimize - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; +void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t* Data, int Width, int Height, int Color) { + if(!Height) Height = Device->Height; + if(!Width) Width = Device->Width; - // end of a column, move to next one - if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + c; } - } - } else if (Device->Depth == 16) { - uint16_t *optr = (uint16_t*) Device->Framebuffer; - int LineLen = Device->Width; - - Height >>= 3; - Color = __builtin_bswap16(Color); - - for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { - uint8_t Byte = BitReverseTable256[*Data++]; - - // we need to linearize code to let compiler better optimize - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - *optr = ((Byte & 0x01) * Color); optr += LineLen; + if(Device->DrawBitmapCBR) { + Device->DrawBitmapCBR(Device, Data, Width, Height, Color); + } else if(Device->Depth == 1) { - // end of a column, move to next one - if (++r == Height) { c++; r = 0; optr = (uint16_t*) Device->Framebuffer + c; } - } - } else if (Device->Depth == 24) { - uint8_t *optr = Device->Framebuffer; - int LineLen = Device->Width * 3; - - Height >>= 3; - if (Device->Mode == GDS_RGB666) Color = ((Color << 4) & 0xff0000) | ((Color << 2) & 0xff00) | (Color & 0x00ff); - - for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { - uint8_t Byte = BitReverseTable256[*Data++]; - - // we need to linearize code to let compiler better optimize - #define SET24(O,D) O[0]=(D)>>16; O[1]=(D)>>8; O[2]=(D); - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; Byte >>= 1; - SET24(optr,(Byte & 0x01) * Color); optr += LineLen; + Height >>= 3; - // end of a column, move to next one - if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + c * 3; } - } - } else { - Height >>= 3; - - // don't know bitdepth, use brute-force solution - for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { - uint8_t Byte = *Data++; - DrawPixelFast( Device, c, (r << 3) + 7, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 6, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 5, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 4, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 3, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 2, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 1, (Byte & 0x01) * Color ); Byte >>= 1; - DrawPixelFast( Device, c, (r << 3) + 0, (Byte & 0x01) * Color ); - if (++r == Height) { c++; r = 0; } - } - /* for better understanding, here is the mundane version + // need to do row/col swap and bit-reverse + for(int r = 0; r < Height; r++) { + uint8_t *optr = Device->Framebuffer + r * Device->Width, *iptr = Data + r; + for(int c = Width; --c >= 0;) { + *optr++ = BitReverseTable256[*iptr]; + iptr += Height; + } + } + } else if(Device->Depth == 4) { + uint8_t* optr = Device->Framebuffer; + int LineLen = Device->Width >> 1; + + Height >>= 3; + Color &= 0x0f; + + for(int i = Width * Height, r = 0, c = 0; --i >= 0;) { + uint8_t Byte = BitReverseTable256[*Data++]; + // we need to linearize code to let compiler better optimize + if(c & 0x01) { + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01) * Color) << 4); + optr += LineLen; + } else { + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01) * Color)); + optr += LineLen; + } + // end of a column, move to next one + if(++r == Height) { + c++; + r = 0; + optr = Device->Framebuffer + (c >> 1); + } + } + } else if(Device->Depth == 8) { + uint8_t* optr = Device->Framebuffer; + int LineLen = Device->Width; + + Height >>= 3; + + for(int i = Width * Height, r = 0, c = 0; --i >= 0;) { + uint8_t Byte = BitReverseTable256[*Data++]; + + // we need to linearize code to let compiler better optimize + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + + // end of a column, move to next one + if(++r == Height) { + c++; + r = 0; + optr = Device->Framebuffer + c; + } + } + } else if(Device->Depth == 16) { + uint16_t* optr = (uint16_t*)Device->Framebuffer; + int LineLen = Device->Width; + + Height >>= 3; + Color = __builtin_bswap16(Color); + + for(int i = Width * Height, r = 0, c = 0; --i >= 0;) { + uint8_t Byte = BitReverseTable256[*Data++]; + + // we need to linearize code to let compiler better optimize + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + *optr = ((Byte & 0x01) * Color); + optr += LineLen; + + // end of a column, move to next one + if(++r == Height) { + c++; + r = 0; + optr = (uint16_t*)Device->Framebuffer + c; + } + } + } else if(Device->Depth == 24) { + uint8_t* optr = Device->Framebuffer; + int LineLen = Device->Width * 3; + + Height >>= 3; + if(Device->Mode == GDS_RGB666) Color = ((Color << 4) & 0xff0000) | ((Color << 2) & 0xff00) | (Color & 0x00ff); + + for(int i = Width * Height, r = 0, c = 0; --i >= 0;) { + uint8_t Byte = BitReverseTable256[*Data++]; + +// we need to linearize code to let compiler better optimize +#define SET24(O, D) \ + O[0] = (D) >> 16; \ + O[1] = (D) >> 8; \ + O[2] = (D); + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + Byte >>= 1; + SET24(optr, (Byte & 0x01) * Color); + optr += LineLen; + + // end of a column, move to next one + if(++r == Height) { + c++; + r = 0; + optr = Device->Framebuffer + c * 3; + } + } + } else { + Height >>= 3; + + // don't know bitdepth, use brute-force solution + for(int i = Width * Height, r = 0, c = 0; --i >= 0;) { + uint8_t Byte = *Data++; + DrawPixelFast(Device, c, (r << 3) + 7, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 6, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 5, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 4, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 3, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 2, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 1, (Byte & 0x01) * Color); + Byte >>= 1; + DrawPixelFast(Device, c, (r << 3) + 0, (Byte & 0x01) * Color); + if(++r == Height) { + c++; + r = 0; + } + } + /* for better understanding, here is the mundane version for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { uint8_t Byte = *Data++; @@ -345,7 +434,7 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int } } */ - } - - Device->Dirty = true; + } + + Device->Dirty = true; } diff --git a/components/display/core/gds_draw.h b/components/display/core/gds_draw.h index d966c01e..1af9f361 100644 --- a/components/display/core/gds_draw.h +++ b/components/display/core/gds_draw.h @@ -5,7 +5,7 @@ * https://opensource.org/licenses/MIT * */ - + #ifndef _GDS_DRAW_H_ #define _GDS_DRAW_H_ @@ -17,14 +17,14 @@ extern "C" { #endif -void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ); -void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int X, int Y, int Color ); -void GDS_DrawHLine( struct GDS_Device* Device, int x, int y, int Width, int Color ); -void GDS_DrawVLine( struct GDS_Device* Device, int x, int y, int Height, int Color ); -void GDS_DrawLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ); -void GDS_DrawBox( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color, bool Fill ); -// draw a bitmap with source 1-bit depth organized in column and col0 = bit7 of byte 0 -void GDS_DrawBitmapCBR( struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color); +void IRAM_ATTR GDS_DrawPixelFast(struct GDS_Device* Device, int X, int Y, int Color); +void IRAM_ATTR GDS_DrawPixel(struct GDS_Device* Device, int X, int Y, int Color); +void GDS_DrawHLine(struct GDS_Device* Device, int x, int y, int Width, int Color); +void GDS_DrawVLine(struct GDS_Device* Device, int x, int y, int Height, int Color); +void GDS_DrawLine(struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color); +void GDS_DrawBox(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color, bool Fill); +// draw a bitmap with source 1-bit depth organized in column and col0 = bit7 of byte 0 +void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t* Data, int Width, int Height, int Color); #ifdef __cplusplus } diff --git a/components/display/core/gds_err.h b/components/display/core/gds_err.h index 827a24c6..624dacb5 100644 --- a/components/display/core/gds_err.h +++ b/components/display/core/gds_err.h @@ -3,36 +3,39 @@ #include -#define GDS_DoAbort( ) +#define GDS_DoAbort() -#if ! defined NullCheck - #define NullCheck( ptr, retexpr ) { \ - if ( ptr == NULL ) { \ - ESP_LOGE( __FUNCTION__, "%s == NULL", #ptr ); \ - GDS_DoAbort( ); \ - retexpr; \ - } \ +#if !defined NullCheck +#define NullCheck(ptr, retexpr) \ + { \ + if(ptr == NULL) { \ + ESP_LOGE(__FUNCTION__, "%s == NULL", #ptr); \ + GDS_DoAbort(); \ + retexpr; \ + } \ } #endif -#if ! defined ESP_ERROR_CHECK_NONFATAL - #define ESP_ERROR_CHECK_NONFATAL( expr, retexpr ) { \ - esp_err_t __err_rc = ( expr ); \ - if ( __err_rc != ESP_OK ) { \ - ESP_LOGE( __FUNCTION__, "%s != ESP_OK, result: %d", #expr, __err_rc ); \ - GDS_DoAbort( ); \ - retexpr; \ - } \ +#if !defined ESP_ERROR_CHECK_NONFATAL +#define ESP_ERROR_CHECK_NONFATAL(expr, retexpr) \ + { \ + esp_err_t __err_rc = (expr); \ + if(__err_rc != ESP_OK) { \ + ESP_LOGE(__FUNCTION__, "%s != ESP_OK, result: %d", #expr, __err_rc); \ + GDS_DoAbort(); \ + retexpr; \ + } \ } #endif -#if ! defined CheckBounds - #define CheckBounds( expr, retexpr ) { \ - if ( expr ) { \ - ESP_LOGE( __FUNCTION__, "Line %d: %s", __LINE__, #expr ); \ - GDS_DoAbort( ); \ - retexpr; \ - } \ +#if !defined CheckBounds +#define CheckBounds(expr, retexpr) \ + { \ + if(expr) { \ + ESP_LOGE(__FUNCTION__, "Line %d: %s", __LINE__, #expr); \ + GDS_DoAbort(); \ + retexpr; \ + } \ } #endif diff --git a/components/display/core/gds_font.c b/components/display/core/gds_font.c index 59fd1858..c7e645ca 100644 --- a/components/display/core/gds_font.c +++ b/components/display/core/gds_font.c @@ -18,10 +18,10 @@ #include "esp_log.h" #include "esp_heap_caps.h" #include "tools.h" -static const char * TAG = "gds_font"; -struct GDS_FontDef * Font_droid_sans_fallback_11x13 = NULL; -struct GDS_FontDef * Font_line_1 = NULL; -struct GDS_FontDef * Font_line_2 = NULL; +static const char* TAG = "gds_font"; +struct GDS_FontDef* Font_droid_sans_fallback_11x13 = NULL; +struct GDS_FontDef* Font_line_1 = NULL; +struct GDS_FontDef* Font_line_2 = NULL; // struct GDS_FontDef * Font_droid_sans_fallback_15x17 = NULL; // struct GDS_FontDef * Font_droid_sans_fallback_24x28 = NULL; @@ -34,19 +34,18 @@ struct GDS_FontDef * Font_line_2 = NULL; // struct GDS_FontDef * Font_Tarable7Seg_16x32 = NULL; // struct GDS_FontDef * Font_Tarable7Seg_32x64 = NULL; - -static bool LoadFont(struct GDS_FontDef ** fontPtr, const char * fileName){ - if(!fontPtr){ +static bool LoadFont(struct GDS_FontDef** fontPtr, const char* fileName) { + if(!fontPtr) { ESP_LOGE(TAG, "Invalid pointer for LoadFont"); return false; } - char font_file_name[CONFIG_SPIFFS_OBJ_NAME_LEN+1]={0}; - snprintf(font_file_name,sizeof(font_file_name),"/spiffs/fonts/%s",fileName); + char font_file_name[CONFIG_SPIFFS_OBJ_NAME_LEN + 1] = {0}; + snprintf(font_file_name, sizeof(font_file_name), "/spiffs/fonts/%s", fileName); // Allocate DMA-capable memory for the font - struct GDS_FontDef* loadedFont = load_file_dma(NULL,font_file_name); + struct GDS_FontDef* loadedFont = load_file_dma(NULL, font_file_name); // Check if allocation succeeded - if (loadedFont == NULL) { + if(loadedFont == NULL) { ESP_LOGE(TAG, "Failed to load font"); return false; } @@ -60,40 +59,32 @@ bool gds_init_fonts() { bool success = true; // Load the Font_droid_sans_fallback_11x13 - if (!LoadFont(&Font_droid_sans_fallback_11x13, "droid_sans_fb_11x13.bin")) { - success = false; - } + if(!LoadFont(&Font_droid_sans_fallback_11x13, "droid_sans_fb_11x13.bin")) { success = false; } // Load the Font_line_1 - if (!LoadFont(&Font_line_1, "line_1.bin")) { - success = false; - } + if(!LoadFont(&Font_line_1, "line_1.bin")) { success = false; } // Load the Font_line_2 - if (!LoadFont(&Font_line_2, "line_2.bin")) { - success = false; - } + if(!LoadFont(&Font_line_2, "line_2.bin")) { success = false; } return success; } -static int RoundUpFontHeight( const struct GDS_FontDef* Font ) { +static int RoundUpFontHeight(const struct GDS_FontDef* Font) { int Height = Font->Height; - if ( ( Height % 8 ) != 0 ) { - return ( ( Height + 7 ) / 8 ) * 8; - } + if((Height % 8) != 0) { return ((Height + 7) / 8) * 8; } return Height; } -static const uint8_t* GetCharPtr( const struct GDS_FontDef* Font, char Character ) { - return &Font->FontData[( Character - Font->StartChar ) * ( ( Font->Width * ( RoundUpFontHeight( Font ) / 8 ) ) + 1 )]; +static const uint8_t* GetCharPtr(const struct GDS_FontDef* Font, char Character) { + return &Font->FontData[(Character - Font->StartChar) * ((Font->Width * (RoundUpFontHeight(Font) / 8)) + 1)]; } -void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y, int Color ) { +void GDS_FontDrawChar(struct GDS_Device* Device, char Character, int x, int y, int Color) { const uint8_t* GlyphData = NULL; int GlyphColumnLen = 0; - int CharStartX = 0; + int CharStartX = 0; int CharStartY = 0; int CharWidth = 0; int CharHeight = 0; @@ -105,62 +96,60 @@ void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y, int YBit = 0; int i = 0; - NullCheck( ( GlyphData = GetCharPtr( Device->Font, Character ) ), return ); + NullCheck((GlyphData = GetCharPtr(Device->Font, Character)), return); - if ( Character >= Device->Font->StartChar && Character <= Device->Font->EndChar ) { + if(Character >= Device->Font->StartChar && Character <= Device->Font->EndChar) { /* The first byte in the glyph data is the width of the character in pixels, skip over */ GlyphData++; - GlyphColumnLen = RoundUpFontHeight( Device->Font ) / 8; - - CharWidth = GDS_FontGetCharWidth( Device, Character ); - CharHeight = GDS_FontGetHeight( Device ); + GlyphColumnLen = RoundUpFontHeight(Device->Font) / 8; + + CharWidth = GDS_FontGetCharWidth(Device, Character); + CharHeight = GDS_FontGetHeight(Device); CharStartX = x; CharStartY = y; - + CharEndX = CharStartX + CharWidth; CharEndY = CharStartY + CharHeight; /* If the character is partially offscreen offset the end by * distance between (coord) and 0. */ - OffsetX = ( CharStartX < 0 ) ? abs( CharStartX ) : 0; - OffsetY = ( CharStartY < 0 ) ? abs( CharStartY ) : 0; + OffsetX = (CharStartX < 0) ? abs(CharStartX) : 0; + OffsetY = (CharStartY < 0) ? abs(CharStartY) : 0; /* This skips into the proper column within the glyph data */ - GlyphData+= ( OffsetX * GlyphColumnLen ); + GlyphData += (OffsetX * GlyphColumnLen); - CharStartX+= OffsetX; - CharStartY+= OffsetY; + CharStartX += OffsetX; + CharStartY += OffsetY; /* Do not attempt to draw if this character is entirely offscreen */ - if ( CharEndX < 0 || CharStartX >= Device->TextWidth || CharEndY < 0 || CharStartY >= Device->Height ) { - ClipDebug( x, y ); + if(CharEndX < 0 || CharStartX >= Device->TextWidth || CharEndY < 0 || CharStartY >= Device->Height) { + ClipDebug(x, y); return; } /* Do not attempt to draw past the end of the screen */ - CharEndX = ( CharEndX >= Device->TextWidth ) ? Device->TextWidth - 1 : CharEndX; - CharEndY = ( CharEndY >= Device->Height ) ? Device->Height - 1 : CharEndY; - Device->Dirty = true; + CharEndX = (CharEndX >= Device->TextWidth) ? Device->TextWidth - 1 : CharEndX; + CharEndY = (CharEndY >= Device->Height) ? Device->Height - 1 : CharEndY; + Device->Dirty = true; - for ( x = CharStartX; x < CharEndX; x++ ) { - for ( y = CharStartY, i = 0; y < CharEndY && i < CharHeight; y++, i++ ) { - YByte = ( i + OffsetY ) / 8; - YBit = ( i + OffsetY ) & 0x07; + for(x = CharStartX; x < CharEndX; x++) { + for(y = CharStartY, i = 0; y < CharEndY && i < CharHeight; y++, i++) { + YByte = (i + OffsetY) / 8; + YBit = (i + OffsetY) & 0x07; - if ( GlyphData[ YByte ] & BIT( YBit ) ) { - DrawPixel( Device, x, y, Color ); - } + if(GlyphData[YByte] & BIT(YBit)) { DrawPixel(Device, x, y, Color); } } - GlyphData+= GlyphColumnLen; + GlyphData += GlyphColumnLen; } } } -const struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ) { - const struct GDS_FontDef* OldFont = Display->Font; +const struct GDS_FontDef* GDS_SetFont(struct GDS_Device* Display, const struct GDS_FontDef* Font) { + const struct GDS_FontDef* OldFont = Display->Font; Display->FontForceProportional = false; Display->FontForceMonospace = false; @@ -169,162 +158,142 @@ const struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct return OldFont; } -void GDS_FontForceProportional( struct GDS_Device* Display, bool Force ) { - Display->FontForceProportional = Force; -} +void GDS_FontForceProportional(struct GDS_Device* Display, bool Force) { Display->FontForceProportional = Force; } -void GDS_FontForceMonospace( struct GDS_Device* Display, bool Force ) { - Display->FontForceMonospace = Force; -} +void GDS_FontForceMonospace(struct GDS_Device* Display, bool Force) { Display->FontForceMonospace = Force; } -int GDS_FontGetWidth( struct GDS_Device* Display ) { - return Display->Font->Width; -} +int GDS_FontGetWidth(struct GDS_Device* Display) { return Display->Font->Width; } -int GDS_FontGetHeight( struct GDS_Device* Display ) { - return Display->Font->Height; -} +int GDS_FontGetHeight(struct GDS_Device* Display) { return Display->Font->Height; } -int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ) { +int GDS_FontGetCharWidth(struct GDS_Device* Display, char Character) { const uint8_t* CharPtr = NULL; int Width = 0; - if ( Character >= Display->Font->StartChar && Character <= Display->Font->EndChar ) { - CharPtr = GetCharPtr( Display->Font, Character ); - Width = ( Display->Font->Monospace == true ) ? Display->Font->Width : *CharPtr; - if ( Display->FontForceMonospace == true ) { - Width = Display->Font->Width; - } + if(Character >= Display->Font->StartChar && Character <= Display->Font->EndChar) { + CharPtr = GetCharPtr(Display->Font, Character); + Width = (Display->Font->Monospace == true) ? Display->Font->Width : *CharPtr; + if(Display->FontForceMonospace == true) { Width = Display->Font->Width; } - if ( Display->FontForceProportional == true ) { - Width = *CharPtr; - } + if(Display->FontForceProportional == true) { Width = *CharPtr; } } return Width; } -int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ) { - return Display->TextWidth / Display->Font->Width; -} +int GDS_FontGetMaxCharsPerRow(struct GDS_Device* Display) { return Display->TextWidth / Display->Font->Width; } -int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ) { - return Display->Height / Display->Font->Height; -} +int GDS_FontGetMaxCharsPerColumn(struct GDS_Device* Display) { return Display->Height / Display->Font->Height; } -int GDS_FontGetCharHeight( struct GDS_Device* Display ) { - return Display->Font->Height; -} +int GDS_FontGetCharHeight(struct GDS_Device* Display) { return Display->Font->Height; } -int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text ) { +int GDS_FontMeasureString(struct GDS_Device* Display, const char* Text) { int Width = 0; int Len = 0; - NullCheck( Text, return 0 ); + NullCheck(Text, return 0); - for ( Len = strlen( Text ); Len >= 0; Len--, Text++ ) { - if ( *Text >= Display->Font->StartChar && *Text <= Display->Font->EndChar ) { - Width+= GDS_FontGetCharWidth( Display, *Text ); - } + for(Len = strlen(Text); Len >= 0; Len--, Text++) { + if(*Text >= Display->Font->StartChar && *Text <= Display->Font->EndChar) { Width += GDS_FontGetCharWidth(Display, *Text); } } return Width; } -void GDS_FontDrawString( struct GDS_Device* Display, int x, int y, const char* Text, int Color ) { +void GDS_FontDrawString(struct GDS_Device* Display, int x, int y, const char* Text, int Color) { int Len = 0; int i = 0; - NullCheck( Text, return ); + NullCheck(Text, return); - for ( Len = strlen( Text ), i = 0; i < Len; i++ ) { - GDS_FontDrawChar( Display, *Text, x, y, Color ); + for(Len = strlen(Text), i = 0; i < Len; i++) { + GDS_FontDrawChar(Display, *Text, x, y, Color); - x+= GDS_FontGetCharWidth( Display, *Text ); + x += GDS_FontGetCharWidth(Display, *Text); Text++; } } -void GDS_FontDrawAnchoredString( struct GDS_Device* Display, TextAnchor Anchor, const char* Text, int Color ) { +void GDS_FontDrawAnchoredString(struct GDS_Device* Display, TextAnchor Anchor, const char* Text, int Color) { int x = 0; int y = 0; - NullCheck( Text, return ); + NullCheck(Text, return); - GDS_FontGetAnchoredStringCoords( Display, &x, &y, Anchor, Text ); - GDS_FontDrawString( Display, x, y, Text, Color ); + GDS_FontGetAnchoredStringCoords(Display, &x, &y, Anchor, Text); + GDS_FontDrawString(Display, x, y, Text, Color); } -void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ) { +void GDS_FontGetAnchoredStringCoords(struct GDS_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text) { int StringWidth = 0; int StringHeight = 0; - NullCheck( OutX, return ); - NullCheck( OutY, return ); - NullCheck( Text, return ); + NullCheck(OutX, return); + NullCheck(OutY, return); + NullCheck(Text, return); - StringWidth = GDS_FontMeasureString( Display, Text ); - StringHeight = GDS_FontGetCharHeight( Display ); + StringWidth = GDS_FontMeasureString(Display, Text); + StringHeight = GDS_FontGetCharHeight(Display); - switch ( Anchor ) { - case TextAnchor_East: { - *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); - *OutX = ( Display->TextWidth - StringWidth ); + switch(Anchor) { + case TextAnchor_East: { + *OutY = (Display->Height / 2) - (StringHeight / 2); + *OutX = (Display->TextWidth - StringWidth); - break; - } - case TextAnchor_West: { - *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); - *OutX = 0; + break; + } + case TextAnchor_West: { + *OutY = (Display->Height / 2) - (StringHeight / 2); + *OutX = 0; - break; - } - case TextAnchor_North: { - *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 ); - *OutY = 0; + break; + } + case TextAnchor_North: { + *OutX = (Display->TextWidth / 2) - (StringWidth / 2); + *OutY = 0; - break; - } - case TextAnchor_South: { - *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 ); - *OutY = ( Display->Height - StringHeight ); - - break; - } - case TextAnchor_NorthEast: { - *OutX = ( Display->TextWidth - StringWidth ); - *OutY = 0; + break; + } + case TextAnchor_South: { + *OutX = (Display->TextWidth / 2) - (StringWidth / 2); + *OutY = (Display->Height - StringHeight); - break; - } - case TextAnchor_NorthWest: { - *OutY = 0; - *OutX = 0; + break; + } + case TextAnchor_NorthEast: { + *OutX = (Display->TextWidth - StringWidth); + *OutY = 0; - break; - } - case TextAnchor_SouthEast: { - *OutY = ( Display->Height - StringHeight ); - *OutX = ( Display->TextWidth - StringWidth ); + break; + } + case TextAnchor_NorthWest: { + *OutY = 0; + *OutX = 0; - break; - } - case TextAnchor_SouthWest: { - *OutY = ( Display->Height - StringHeight ); - *OutX = 0; + break; + } + case TextAnchor_SouthEast: { + *OutY = (Display->Height - StringHeight); + *OutX = (Display->TextWidth - StringWidth); - break; - } - case TextAnchor_Center: { - *OutY = ( Display->Height / 2 ) - ( StringHeight / 2 ); - *OutX = ( Display->TextWidth / 2 ) - ( StringWidth / 2 ); + break; + } + case TextAnchor_SouthWest: { + *OutY = (Display->Height - StringHeight); + *OutX = 0; - break; - } - default: { - *OutX = 128; - *OutY = 64; - - break; - } + break; + } + case TextAnchor_Center: { + *OutY = (Display->Height / 2) - (StringHeight / 2); + *OutX = (Display->TextWidth / 2) - (StringWidth / 2); + + break; + } + default: { + *OutX = 128; + *OutY = 64; + + break; + } }; } diff --git a/components/display/core/gds_font.h b/components/display/core/gds_font.h index 7b904c46..666bf837 100644 --- a/components/display/core/gds_font.h +++ b/components/display/core/gds_font.h @@ -21,23 +21,22 @@ struct GDS_Device; * 'b': [Glyph width][Pixel column 0][Pixel column 1]... * 'c': And so on... */ - -#pragma pack(push, 1) // Disable padding + +#pragma pack(push, 1) // Disable padding struct GDS_FontDef { - const void* dummy; // 4 bytes (assuming 32-bit pointers) + const void* dummy; // 4 bytes (assuming 32-bit pointers) - int Width; // 4 bytes - int Height; // 4 bytes - int StartChar; // 4 bytes - int EndChar; // 4 bytes - bool Monospace; // 1 byte + int Width; // 4 bytes + int Height; // 4 bytes + int StartChar; // 4 bytes + int EndChar; // 4 bytes + bool Monospace; // 1 byte - uint8_t padding[3]; // 3 bytes padding to align to 24 bytes - const uint8_t FontData[]; // 4 bytes (assuming 32-bit pointers) + uint8_t padding[3]; // 3 bytes padding to align to 24 bytes + const uint8_t FontData[]; // 4 bytes (assuming 32-bit pointers) }; #pragma pack(pop) // Re-enable padding - typedef enum { TextAnchor_East = 0, TextAnchor_West, @@ -50,28 +49,28 @@ typedef enum { TextAnchor_Center } TextAnchor; bool gds_init_fonts(); -const struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ); +const struct GDS_FontDef* GDS_SetFont(struct GDS_Device* Display, const struct GDS_FontDef* Font); -void GDS_FontForceProportional( struct GDS_Device* Display, bool Force ); -void GDS_FontForceMonospace( struct GDS_Device* Display, bool Force ); +void GDS_FontForceProportional(struct GDS_Device* Display, bool Force); +void GDS_FontForceMonospace(struct GDS_Device* Display, bool Force); -int GDS_FontGetWidth( struct GDS_Device* Display ); -int GDS_FontGetHeight( struct GDS_Device* Display ); +int GDS_FontGetWidth(struct GDS_Device* Display); +int GDS_FontGetHeight(struct GDS_Device* Display); -int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ); -int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ); +int GDS_FontGetMaxCharsPerRow(struct GDS_Device* Display); +int GDS_FontGetMaxCharsPerColumn(struct GDS_Device* Display); -int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ); -int GDS_FontGetCharHeight( struct GDS_Device* Display ); -int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text ); -int GDS_FontMeasureStringLine( struct GDS_Device* Display, int Line, const char* Text ); +int GDS_FontGetCharWidth(struct GDS_Device* Display, char Character); +int GDS_FontGetCharHeight(struct GDS_Device* Display); +int GDS_FontMeasureString(struct GDS_Device* Display, const char* Text); +int GDS_FontMeasureStringLine(struct GDS_Device* Display, int Line, const char* Text); -void GDS_FontDrawChar( struct GDS_Device* Display, char Character, int x, int y, int Color ); -void GDS_FontDrawString( struct GDS_Device* Display, int x, int y, const char* Text, int Color ); -void GDS_FontDrawAnchoredString( struct GDS_Device* Display, TextAnchor Anchor, const char* Text, int Color ); -void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ); +void GDS_FontDrawChar(struct GDS_Device* Display, char Character, int x, int y, int Color); +void GDS_FontDrawString(struct GDS_Device* Display, int x, int y, const char* Text, int Color); +void GDS_FontDrawAnchoredString(struct GDS_Device* Display, TextAnchor Anchor, const char* Text, int Color); +void GDS_FontGetAnchoredStringCoords(struct GDS_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text); -extern struct GDS_FontDef * Font_droid_sans_fallback_11x13; +extern struct GDS_FontDef* Font_droid_sans_fallback_11x13; // const struct GDS_FontDef * Font_droid_sans_fallback_15x17; // const struct GDS_FontDef * Font_droid_sans_fallback_24x28; @@ -86,8 +85,8 @@ extern struct GDS_FontDef * Font_droid_sans_fallback_11x13; // const struct GDS_FontDef * Font_Tarable7Seg_16x32; // const struct GDS_FontDef * Font_Tarable7Seg_32x64; -extern struct GDS_FontDef * Font_line_1; -extern struct GDS_FontDef * Font_line_2; +extern struct GDS_FontDef* Font_line_1; +extern struct GDS_FontDef* Font_line_2; #ifdef __cplusplus } diff --git a/components/display/core/gds_image.c b/components/display/core/gds_image.c index 5d209819..3ac357ec 100644 --- a/components/display/core/gds_image.c +++ b/components/display/core/gds_image.c @@ -5,7 +5,7 @@ * https://opensource.org/licenses/MIT * */ - + #include #include "math.h" #ifdef TJPGD_ROM @@ -21,23 +21,23 @@ const static char TAG[] = "ImageDec"; -#define SCRATCH_SIZE 3100 +#define SCRATCH_SIZE 3100 //Data that is passed from the decoder function to the infunc/outfunc functions. typedef struct { - const unsigned char *InData; // Pointer to jpeg data - int InPos; // Current position in jpeg data - int Width, Height; - uint8_t Mode; - union { - void *OutData; - struct { // DirectDraw - struct GDS_Device *Device; - int XOfs, YOfs; - int XMin, YMin; - int Depth; - }; - }; + const unsigned char* InData; // Pointer to jpeg data + int InPos; // Current position in jpeg data + int Width, Height; + uint8_t Mode; + union { + void* OutData; + struct { // DirectDraw + struct GDS_Device* Device; + int XOfs, YOfs; + int XMin, YMin; + int Depth; + }; + }; } JpegCtx; /**************************************************************************************** @@ -46,192 +46,182 @@ typedef struct { * monochrome (0.2125 * color.r) + (0.7154 * color.g) + (0.0721 * color.b) * grayscale (0.3 * R) + (0.59 * G) + (0.11 * B) ) */ -static inline int Scaler332(uint8_t *Pixels) { - return (Pixels[2] & ~0x1f) | ((Pixels[1] & ~0x1f) >> 3) | (Pixels[0] >> 6); -} +static inline int Scaler332(uint8_t* Pixels) { return (Pixels[2] & ~0x1f) | ((Pixels[1] & ~0x1f) >> 3) | (Pixels[0] >> 6); } -static inline int Scaler444(uint8_t *Pixels) { - return ((Pixels[2] & ~0x0f) << 4) | (Pixels[1] & ~0x0f) | (Pixels[0] >> 4); -} +static inline int Scaler444(uint8_t* Pixels) { return ((Pixels[2] & ~0x0f) << 4) | (Pixels[1] & ~0x0f) | (Pixels[0] >> 4); } -static inline int Scaler555(uint8_t *Pixels) { - return ((Pixels[2] & ~0x07) << 7) | ((Pixels[1] & ~0x07) << 2) | (Pixels[0] >> 3); -} +static inline int Scaler555(uint8_t* Pixels) { return ((Pixels[2] & ~0x07) << 7) | ((Pixels[1] & ~0x07) << 2) | (Pixels[0] >> 3); } -static inline int Scaler565(uint8_t *Pixels) { - return ((Pixels[2] & ~0x07) << 8) | ((Pixels[1] & ~0x03) << 3) | (Pixels[0] >> 3); -} +static inline int Scaler565(uint8_t* Pixels) { return ((Pixels[2] & ~0x07) << 8) | ((Pixels[1] & ~0x03) << 3) | (Pixels[0] >> 3); } -static inline int Scaler666(uint8_t *Pixels) { - return ((Pixels[2] & ~0x03) << 10) | ((Pixels[1] & ~0x03) << 4) | (Pixels[0] >> 2); -} +static inline int Scaler666(uint8_t* Pixels) { return ((Pixels[2] & ~0x03) << 10) | ((Pixels[1] & ~0x03) << 4) | (Pixels[0] >> 2); } -static inline int Scaler888(uint8_t *Pixels) { - return (Pixels[2] << 16) | (Pixels[1] << 8) | Pixels[0]; -} +static inline int Scaler888(uint8_t* Pixels) { return (Pixels[2] << 16) | (Pixels[1] << 8) | Pixels[0]; } -static inline int ScalerGray(uint8_t *Pixels) { - return (Pixels[2] * 14 + Pixels[1] * 76 + Pixels[0] * 38) >> 7; -} +static inline int ScalerGray(uint8_t* Pixels) { return (Pixels[2] * 14 + Pixels[1] * 76 + Pixels[0] * 38) >> 7; } -static unsigned InHandler(JDEC *Decoder, uint8_t *Buf, unsigned Len) { - JpegCtx *Context = (JpegCtx*) Decoder->device; - if (Buf) memcpy(Buf, Context->InData + Context->InPos, Len); +static unsigned InHandler(JDEC* Decoder, uint8_t* Buf, unsigned Len) { + JpegCtx* Context = (JpegCtx*)Decoder->device; + if(Buf) memcpy(Buf, Context->InData + Context->InPos, Len); Context->InPos += Len; return Len; } -#define OUTHANDLER(F) \ - for (int y = Frame->top; y <= Frame->bottom; y++) { \ - for (int x = Frame->left; x <= Frame->right; x++) { \ - OutData[Context->Width * y + x] = F(Pixels); \ - Pixels += 3; \ - } \ - } - -#define OUTHANDLER24(F) \ - for (int y = Frame->top; y <= Frame->bottom; y++) { \ - uint8_t *p = OutData + (Context->Width * y + Frame->left) * 3; \ - for (int c = Frame->right - Frame->left; c-- >= 0;) { \ - uint32_t v = F(Pixels); \ - *p++ = v; *p++ = v >> 8; *p++ = v >> 16; \ - Pixels += 3; \ - } \ - } +#define OUTHANDLER(F) \ + for(int y = Frame->top; y <= Frame->bottom; y++) { \ + for(int x = Frame->left; x <= Frame->right; x++) { \ + OutData[Context->Width * y + x] = F(Pixels); \ + Pixels += 3; \ + } \ + } -static unsigned OutHandler(JDEC *Decoder, void *Bitmap, JRECT *Frame) { - JpegCtx *Context = (JpegCtx*) Decoder->device; - uint8_t *Pixels = (uint8_t*) Bitmap; +#define OUTHANDLER24(F) \ + for(int y = Frame->top; y <= Frame->bottom; y++) { \ + uint8_t* p = OutData + (Context->Width * y + Frame->left) * 3; \ + for(int c = Frame->right - Frame->left; c-- >= 0;) { \ + uint32_t v = F(Pixels); \ + *p++ = v; \ + *p++ = v >> 8; \ + *p++ = v >> 16; \ + Pixels += 3; \ + } \ + } + +static unsigned OutHandler(JDEC* Decoder, void* Bitmap, JRECT* Frame) { + JpegCtx* Context = (JpegCtx*)Decoder->device; + uint8_t* Pixels = (uint8_t*)Bitmap; + + // decoded image is RGB888 + if(Context->Mode == GDS_RGB888) { + uint8_t* OutData = (uint8_t*)Context->OutData; + OUTHANDLER24(Scaler888); + } else if(Context->Mode == GDS_RGB666) { + uint8_t* OutData = (uint8_t*)Context->OutData; + OUTHANDLER24(Scaler666); + } else if(Context->Mode == GDS_RGB565) { + uint16_t* OutData = (uint16_t*)Context->OutData; + OUTHANDLER(Scaler565); + } else if(Context->Mode == GDS_RGB555) { + uint16_t* OutData = (uint16_t*)Context->OutData; + OUTHANDLER(Scaler555); + } else if(Context->Mode == GDS_RGB444) { + uint16_t* OutData = (uint16_t*)Context->OutData; + OUTHANDLER(Scaler444); + } else if(Context->Mode == GDS_RGB332) { + uint8_t* OutData = (uint8_t*)Context->OutData; + OUTHANDLER(Scaler332); + } else if(Context->Mode <= GDS_GRAYSCALE) { + uint8_t* OutData = (uint8_t*)Context->OutData; + OUTHANDLER(ScalerGray); + } - // decoded image is RGB888 - if (Context->Mode == GDS_RGB888) { - uint8_t *OutData = (uint8_t*) Context->OutData; - OUTHANDLER24(Scaler888); - } else if (Context->Mode == GDS_RGB666) { - uint8_t *OutData = (uint8_t*) Context->OutData; - OUTHANDLER24(Scaler666); - } else if (Context->Mode == GDS_RGB565) { - uint16_t *OutData = (uint16_t*) Context->OutData; - OUTHANDLER(Scaler565); - } else if (Context->Mode == GDS_RGB555) { - uint16_t *OutData = (uint16_t*) Context->OutData; - OUTHANDLER(Scaler555); - } else if (Context->Mode == GDS_RGB444) { - uint16_t *OutData = (uint16_t*) Context->OutData; - OUTHANDLER(Scaler444); - } else if (Context->Mode == GDS_RGB332) { - uint8_t *OutData = (uint8_t*) Context->OutData; - OUTHANDLER(Scaler332); - } else if (Context->Mode <= GDS_GRAYSCALE) { - uint8_t *OutData = (uint8_t*) Context->OutData; - OUTHANDLER(ScalerGray); - } - return 1; } -// Convert the RGB888 to destination color plane, use DrawPixel and not "fast" -// version as X,Y may be beyond screen -#define OUTHANDLERDIRECT(F,S) \ - for (int y = Frame->top; y <= Frame->bottom; y++) { \ - if (y < Context->YMin) continue; \ - for (int x = Frame->left; x <= Frame->right; x++) { \ - if (x < Context->XMin) continue; \ - DrawPixel( Context->Device, x + Context->XOfs, y + Context->YOfs, F(Pixels) >> S); \ - Pixels += 3; \ - } \ - } - -static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) { - JpegCtx *Context = (JpegCtx*) Decoder->device; - uint8_t *Pixels = (uint8_t*) Bitmap; - int Shift = 8 - Context->Depth; - - // decoded image is RGB888, shift only make sense for grayscale - if (Context->Mode == GDS_RGB888) { - OUTHANDLERDIRECT(Scaler888, 0); - } else if (Context->Mode == GDS_RGB666) { - OUTHANDLERDIRECT(Scaler666, 0); - } else if (Context->Mode == GDS_RGB565) { - OUTHANDLERDIRECT(Scaler565, 0); - } else if (Context->Mode == GDS_RGB555) { - OUTHANDLERDIRECT(Scaler555, 0); - } else if (Context->Mode == GDS_RGB444) { - OUTHANDLERDIRECT(Scaler444, 0); - } else if (Context->Mode == GDS_RGB332) { - OUTHANDLERDIRECT(Scaler332, 0); - } else if (Context->Mode <= GDS_GRAYSCALE) { - OUTHANDLERDIRECT(ScalerGray, Shift); - } - +// Convert the RGB888 to destination color plane, use DrawPixel and not "fast" +// version as X,Y may be beyond screen +#define OUTHANDLERDIRECT(F, S) \ + for(int y = Frame->top; y <= Frame->bottom; y++) { \ + if(y < Context->YMin) continue; \ + for(int x = Frame->left; x <= Frame->right; x++) { \ + if(x < Context->XMin) continue; \ + DrawPixel(Context->Device, x + Context->XOfs, y + Context->YOfs, F(Pixels) >> S); \ + Pixels += 3; \ + } \ + } + +static unsigned OutHandlerDirect(JDEC* Decoder, void* Bitmap, JRECT* Frame) { + JpegCtx* Context = (JpegCtx*)Decoder->device; + uint8_t* Pixels = (uint8_t*)Bitmap; + int Shift = 8 - Context->Depth; + + // decoded image is RGB888, shift only make sense for grayscale + if(Context->Mode == GDS_RGB888) { + OUTHANDLERDIRECT(Scaler888, 0); + } else if(Context->Mode == GDS_RGB666) { + OUTHANDLERDIRECT(Scaler666, 0); + } else if(Context->Mode == GDS_RGB565) { + OUTHANDLERDIRECT(Scaler565, 0); + } else if(Context->Mode == GDS_RGB555) { + OUTHANDLERDIRECT(Scaler555, 0); + } else if(Context->Mode == GDS_RGB444) { + OUTHANDLERDIRECT(Scaler444, 0); + } else if(Context->Mode == GDS_RGB332) { + OUTHANDLERDIRECT(Scaler332, 0); + } else if(Context->Mode <= GDS_GRAYSCALE) { + OUTHANDLERDIRECT(ScalerGray, Shift); + } + return 1; } //Decode the embedded image into pixel lines that can be used with the rest of the logic. -static void* DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, bool SizeOnly, int RGB_Mode) { +static void* DecodeJPEG(uint8_t* Source, int* Width, int* Height, float Scale, bool SizeOnly, int RGB_Mode) { JDEC Decoder; JpegCtx Context; - char *Scratch = malloc(SCRATCH_SIZE); - - if (!Scratch) { + char* Scratch = malloc(SCRATCH_SIZE); + + if(!Scratch) { ESP_LOGE(TAG, "Cannot allocate workspace"); return NULL; } - Context.OutData = NULL; + Context.OutData = NULL; Context.InData = Source; Context.InPos = 0; - + //Prepare and decode the jpeg. - int Res = jd_prepare(&Decoder, InHandler, Scratch, SCRATCH_SIZE, (void*) &Context); - if (Width) *Width = Decoder.width; - if (Height) *Height = Decoder.height; - Decoder.scale = Scale; + int Res = jd_prepare(&Decoder, InHandler, Scratch, SCRATCH_SIZE, (void*)&Context); + if(Width) *Width = Decoder.width; + if(Height) *Height = Decoder.height; + Decoder.scale = Scale; - if (Res == JDR_OK && !SizeOnly) { - if (RGB_Mode <= GDS_RGB332) Context.OutData = malloc(Decoder.width * Decoder.height); - else if (RGB_Mode < GDS_RGB666) Context.OutData = malloc(Decoder.width * Decoder.height * 2); - else if (RGB_Mode <= GDS_RGB888) Context.OutData = malloc(Decoder.width * Decoder.height * 3); - - // find the scaling factor - uint8_t N = 0, ScaleInt = ceil(1.0 / Scale); - ScaleInt--; ScaleInt |= ScaleInt >> 1; ScaleInt |= ScaleInt >> 2; ScaleInt++; - while (ScaleInt >>= 1) N++; - if (N > 3) { - ESP_LOGW(TAG, "Image will not fit %dx%d", Decoder.width, Decoder.height); - N = 3; - } - - // ready to decode - if (Context.OutData) { - Context.Width = Decoder.width / (1 << N); - Context.Height = Decoder.height / (1 << N); - Context.Mode = RGB_Mode; - if (Width) *Width = Context.Width; - if (Height) *Height = Context.Height; - Res = jd_decomp(&Decoder, OutHandler, N); - if (Res != JDR_OK) { - ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", Res); - } - } else { - ESP_LOGE(TAG, "Can't allocate bitmap %dx%d or invalid mode %d", Decoder.width, Decoder.height, RGB_Mode); - } - } else if (!SizeOnly) { + if(Res == JDR_OK && !SizeOnly) { + if(RGB_Mode <= GDS_RGB332) + Context.OutData = malloc(Decoder.width * Decoder.height); + else if(RGB_Mode < GDS_RGB666) + Context.OutData = malloc(Decoder.width * Decoder.height * 2); + else if(RGB_Mode <= GDS_RGB888) + Context.OutData = malloc(Decoder.width * Decoder.height * 3); + + // find the scaling factor + uint8_t N = 0, ScaleInt = ceil(1.0 / Scale); + ScaleInt--; + ScaleInt |= ScaleInt >> 1; + ScaleInt |= ScaleInt >> 2; + ScaleInt++; + while(ScaleInt >>= 1) N++; + if(N > 3) { + ESP_LOGW(TAG, "Image will not fit %dx%d", Decoder.width, Decoder.height); + N = 3; + } + + // ready to decode + if(Context.OutData) { + Context.Width = Decoder.width / (1 << N); + Context.Height = Decoder.height / (1 << N); + Context.Mode = RGB_Mode; + if(Width) *Width = Context.Width; + if(Height) *Height = Context.Height; + Res = jd_decomp(&Decoder, OutHandler, N); + if(Res != JDR_OK) { ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", Res); } + } else { + ESP_LOGE(TAG, "Can't allocate bitmap %dx%d or invalid mode %d", Decoder.width, Decoder.height, RGB_Mode); + } + } else if(!SizeOnly) { ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", Res); - } + } - // free scratch area - if (Scratch) free(Scratch); + // free scratch area + if(Scratch) free(Scratch); return Context.OutData; } -void* GDS_DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, int RGB_Mode) { - return DecodeJPEG(Source, Width, Height, Scale, false, RGB_Mode); -} +void* GDS_DecodeJPEG(uint8_t* Source, int* Width, int* Height, float Scale, int RGB_Mode) { + return DecodeJPEG(Source, Width, Height, Scale, false, RGB_Mode); +} -void GDS_GetJPEGSize(uint8_t *Source, int *Width, int *Height) { - DecodeJPEG(Source, Width, Height, 1, true, -1); -} +void GDS_GetJPEGSize(uint8_t* Source, int* Width, int* Height) { DecodeJPEG(Source, Width, Height, 1, true, -1); } /**************************************************************************************** * RGB conversion (24 bits: RRRRRRRRGGGGGGGGBBBBBBBB and 16 bits 565: RRRRRGGGGGGBBBBB = B31..B0) @@ -239,146 +229,144 @@ void GDS_GetJPEGSize(uint8_t *Source, int *Width, int *Height) { * monochrome (0.2125 * color.r) + (0.7154 * color.g) + (0.0721 * color.b) * grayscale (0.3 * R) + (0.59 * G) + (0.11 * B) ) */ - -static inline int ToGray888(uint8_t **Pixel) { - uint32_t v = *(*Pixel)++; v |= *(*Pixel)++ << 8; v |= *(*Pixel)++ << 16; - return (((v & 0xff) * 14) + ((v >> 8) & 0xff) * 76 + ((v >> 16) * 38) + 1) >> 7; -} - -static inline int ToGray666(uint8_t **Pixel) { - uint32_t v = *(*Pixel)++; v |= *(*Pixel)++ << 8; v |= *(*Pixel)++ << 16; - return (((v & 0x3f) * 14) + ((v >> 6) & 0x3f) * 76 + ((v >> 12) * 38) + 1) >> 7; + +static inline int ToGray888(uint8_t** Pixel) { + uint32_t v = *(*Pixel)++; + v |= *(*Pixel)++ << 8; + v |= *(*Pixel)++ << 16; + return (((v & 0xff) * 14) + ((v >> 8) & 0xff) * 76 + ((v >> 16) * 38) + 1) >> 7; } -static inline int ToGray565(uint16_t **Pixel) { - uint16_t v = *(*Pixel)++; - return ((((v & 0x1f) * 14) << 1) + ((v >> 5) & 0x3f) * 76 + (((v >> 11) * 38) << 1) + 1) >> 7; +static inline int ToGray666(uint8_t** Pixel) { + uint32_t v = *(*Pixel)++; + v |= *(*Pixel)++ << 8; + v |= *(*Pixel)++ << 16; + return (((v & 0x3f) * 14) + ((v >> 6) & 0x3f) * 76 + ((v >> 12) * 38) + 1) >> 7; } -static inline int ToGray555(uint16_t **Pixel) { - uint16_t v = *(*Pixel)++; - return ((v & 0x1f) * 14 + ((v >> 5) & 0x1f) * 76 + (v >> 10) * 38) >> 7; +static inline int ToGray565(uint16_t** Pixel) { + uint16_t v = *(*Pixel)++; + return ((((v & 0x1f) * 14) << 1) + ((v >> 5) & 0x3f) * 76 + (((v >> 11) * 38) << 1) + 1) >> 7; } -static inline int ToGray444(uint16_t **Pixel) { - uint16_t v = *(*Pixel)++; - return ((v & 0x0f) * 14 + ((v >> 4) & 0x0f) * 76 + (v >> 8) * 38) >> 7; +static inline int ToGray555(uint16_t** Pixel) { + uint16_t v = *(*Pixel)++; + return ((v & 0x1f) * 14 + ((v >> 5) & 0x1f) * 76 + (v >> 10) * 38) >> 7; } -static inline int ToGray332(uint8_t **Pixel) { - uint8_t v = *(*Pixel)++; - return ((((v & 0x3) * 14) << 1) + ((v >> 2) & 0x7) * 76 + (v >> 5) * 38 + 1) >> 7; +static inline int ToGray444(uint16_t** Pixel) { + uint16_t v = *(*Pixel)++; + return ((v & 0x0f) * 14 + ((v >> 4) & 0x0f) * 76 + (v >> 8) * 38) >> 7; } -static inline int ToSelf(uint8_t **Pixel) { - return *(*Pixel)++; +static inline int ToGray332(uint8_t** Pixel) { + uint8_t v = *(*Pixel)++; + return ((((v & 0x3) * 14) << 1) + ((v >> 2) & 0x7) * 76 + (v >> 5) * 38 + 1) >> 7; } - -#define DRAW_GRAYRGB(S,F) \ - if (Scale > 0) { \ - for (int r = 0; r < Height; r++) { \ - for (int c = 0; c < Width; c++) { \ - DrawPixel( Device, c + x, r + y, F(S) >> Scale); \ - } \ - } \ - } else { \ - for (int r = 0; r < Height; r++) { \ - for (int c = 0; c < Width; c++) { \ - DrawPixel( Device, c + x, r + y, F(S) << -Scale); \ - } \ - } \ - } - -#define DRAW_RGB(T) \ - T *S = (T*) Image; \ - for (int r = 0; r < Height; r++) { \ - for (int c = 0; c < Width; c++) { \ - DrawPixel(Device, c + x, r + y, *S++); \ - } \ - } - -#define DRAW_RGB24 \ - uint8_t *S = (uint8_t*) Image; \ - for (int r = 0; r < Height; r++) { \ - for (int c = 0; c < Width; c++) { \ - uint32_t v = *S++; v |= *S++ << 8; v |= *S++ << 16; \ - DrawPixel(Device, c + x, r + y, v); \ - } \ - } + +static inline int ToSelf(uint8_t** Pixel) { return *(*Pixel)++; } + +#define DRAW_GRAYRGB(S, F) \ + if(Scale > 0) { \ + for(int r = 0; r < Height; r++) { \ + for(int c = 0; c < Width; c++) { DrawPixel(Device, c + x, r + y, F(S) >> Scale); } \ + } \ + } else { \ + for(int r = 0; r < Height; r++) { \ + for(int c = 0; c < Width; c++) { DrawPixel(Device, c + x, r + y, F(S) << -Scale); } \ + } \ + } + +#define DRAW_RGB(T) \ + T* S = (T*)Image; \ + for(int r = 0; r < Height; r++) { \ + for(int c = 0; c < Width; c++) { DrawPixel(Device, c + x, r + y, *S++); } \ + } + +#define DRAW_RGB24 \ + uint8_t* S = (uint8_t*)Image; \ + for(int r = 0; r < Height; r++) { \ + for(int c = 0; c < Width; c++) { \ + uint32_t v = *S++; \ + v |= *S++ << 8; \ + v |= *S++ << 16; \ + DrawPixel(Device, c + x, r + y, v); \ + } \ + } /**************************************************************************************** * Decode the embedded image into pixel lines that can be used with the rest of the logic. */ -void GDS_DrawRGB( struct GDS_Device* Device, uint8_t *Image, int x, int y, int Width, int Height, int RGB_Mode ) { +void GDS_DrawRGB(struct GDS_Device* Device, uint8_t* Image, int x, int y, int Width, int Height, int RGB_Mode) { - // don't do anything if driver supplies a draw function - if (Device->DrawRGB) { - Device->DrawRGB( Device, Image, x, y, Width, Height, RGB_Mode ); - Device->Dirty = true; - return; - } - - // RGB type displays - if (Device->Mode > GDS_GRAYSCALE) { - // image must match the display mode! - if (Device->Mode != RGB_Mode) { - ESP_LOGE(TAG, "non-matching display & image mode %u %u", Device->Mode, RGB_Mode); - return; - } - - if (RGB_Mode == GDS_RGB332) { - DRAW_RGB(uint8_t); - } else if (RGB_Mode < GDS_RGB666) { - DRAW_RGB(uint16_t); - } else { - DRAW_RGB24; - } - - Device->Dirty = true; - return; - } - - // set the right scaler when displaying grayscale - if (RGB_Mode <= GDS_GRAYSCALE) { - int Scale = 8 - Device->Depth; - DRAW_GRAYRGB(&Image,ToSelf); - } else if (RGB_Mode == GDS_RGB332) { - int Scale = 3 - Device->Depth; - DRAW_GRAYRGB(&Image,ToGray332); - } else if (RGB_Mode < GDS_RGB666) { - if (RGB_Mode == GDS_RGB565) { - int Scale = 6 - Device->Depth; - DRAW_GRAYRGB((uint16_t**)&Image,ToGray565); - } else if (RGB_Mode == GDS_RGB555) { - int Scale = 5 - Device->Depth; - DRAW_GRAYRGB((uint16_t**)&Image,ToGray555); - } else if (RGB_Mode == GDS_RGB444) { - int Scale = 4 - Device->Depth; - DRAW_GRAYRGB((uint16_t**)&Image,ToGray444) - } - } else { - if (RGB_Mode == GDS_RGB666) { - int Scale = 6 - Device->Depth; - DRAW_GRAYRGB(&Image,ToGray666); - } else if (RGB_Mode == GDS_RGB888) { - int Scale = 8 - Device->Depth; - DRAW_GRAYRGB(&Image,ToGray888); - } - } - - Device->Dirty = true; + // don't do anything if driver supplies a draw function + if(Device->DrawRGB) { + Device->DrawRGB(Device, Image, x, y, Width, Height, RGB_Mode); + Device->Dirty = true; + return; + } + + // RGB type displays + if(Device->Mode > GDS_GRAYSCALE) { + // image must match the display mode! + if(Device->Mode != RGB_Mode) { + ESP_LOGE(TAG, "non-matching display & image mode %u %u", Device->Mode, RGB_Mode); + return; + } + + if(RGB_Mode == GDS_RGB332) { + DRAW_RGB(uint8_t); + } else if(RGB_Mode < GDS_RGB666) { + DRAW_RGB(uint16_t); + } else { + DRAW_RGB24; + } + + Device->Dirty = true; + return; + } + + // set the right scaler when displaying grayscale + if(RGB_Mode <= GDS_GRAYSCALE) { + int Scale = 8 - Device->Depth; + DRAW_GRAYRGB(&Image, ToSelf); + } else if(RGB_Mode == GDS_RGB332) { + int Scale = 3 - Device->Depth; + DRAW_GRAYRGB(&Image, ToGray332); + } else if(RGB_Mode < GDS_RGB666) { + if(RGB_Mode == GDS_RGB565) { + int Scale = 6 - Device->Depth; + DRAW_GRAYRGB((uint16_t**)&Image, ToGray565); + } else if(RGB_Mode == GDS_RGB555) { + int Scale = 5 - Device->Depth; + DRAW_GRAYRGB((uint16_t**)&Image, ToGray555); + } else if(RGB_Mode == GDS_RGB444) { + int Scale = 4 - Device->Depth; + DRAW_GRAYRGB((uint16_t**)&Image, ToGray444) + } + } else { + if(RGB_Mode == GDS_RGB666) { + int Scale = 6 - Device->Depth; + DRAW_GRAYRGB(&Image, ToGray666); + } else if(RGB_Mode == GDS_RGB888) { + int Scale = 8 - Device->Depth; + DRAW_GRAYRGB(&Image, ToGray888); + } + } + + Device->Dirty = true; } /**************************************************************************************** * Decode the embedded image into pixel lines that can be used with the rest of the logic. */ -bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t *Source, int x, int y, int Fit) { +bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t* Source, int x, int y, int Fit) { JDEC Decoder; JpegCtx Context; - bool Ret = false; - char *Scratch = malloc(SCRATCH_SIZE); - - if (!Scratch) { + bool Ret = false; + char* Scratch = malloc(SCRATCH_SIZE); + + if(!Scratch) { ESP_LOGE(TAG, "Cannot allocate workspace"); return NULL; } @@ -386,57 +374,63 @@ bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t *Source, int x, int y, int // Populate fields of the JpegCtx struct. Context.InData = Source; Context.InPos = 0; - Context.XOfs = x; - Context.YOfs = y; - Context.Device = Device; - Context.Depth = Device->Depth; - + Context.XOfs = x; + Context.YOfs = y; + Context.Device = Device; + Context.Depth = Device->Depth; + //Prepare and decode the jpeg. - int Res = jd_prepare(&Decoder, InHandler, Scratch, SCRATCH_SIZE, (void*) &Context); - Context.Width = Decoder.width; - Context.Height = Decoder.height; - - if (Res == JDR_OK) { - uint8_t N = 0; - - // do we need to fit the image - if (Fit & GDS_IMAGE_FIT) { - float XRatio = (Device->Width - x) / (float) Decoder.width, YRatio = (Device->Height - y) / (float) Decoder.height; - uint8_t Ratio = XRatio < YRatio ? ceil(1/XRatio) : ceil(1/YRatio); - Ratio--; Ratio |= Ratio >> 1; Ratio |= Ratio >> 2; Ratio++; - while (Ratio >>= 1) N++; - if (N > 3) { - ESP_LOGW(TAG, "Image will not fit %dx%d", Decoder.width, Decoder.height); - N = 3; - } - Context.Width /= 1 << N; - Context.Height /= 1 << N; - } - - // then place it - if (Fit & GDS_IMAGE_CENTER_X) Context.XOfs = (Device->Width + x - Context.Width) / 2; - else if (Fit & GDS_IMAGE_RIGHT) Context.XOfs = Device->Width - Context.Width; - if (Fit & GDS_IMAGE_CENTER_Y) Context.YOfs = (Device->Height + y - Context.Height) / 2; - else if (Fit & GDS_IMAGE_BOTTOM) Context.YOfs = Device->Height - Context.Height; + int Res = jd_prepare(&Decoder, InHandler, Scratch, SCRATCH_SIZE, (void*)&Context); + Context.Width = Decoder.width; + Context.Height = Decoder.height; - Context.XMin = x - Context.XOfs; - Context.YMin = y - Context.YOfs; - Context.Mode = Device->Mode; - - // do decompress & draw - Res = jd_decomp(&Decoder, OutHandlerDirect, N); - if (Res == JDR_OK) { - Device->Dirty = true; - Ret = true; - } else { - ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", Res); - } - } else { + if(Res == JDR_OK) { + uint8_t N = 0; + + // do we need to fit the image + if(Fit & GDS_IMAGE_FIT) { + float XRatio = (Device->Width - x) / (float)Decoder.width, YRatio = (Device->Height - y) / (float)Decoder.height; + uint8_t Ratio = XRatio < YRatio ? ceil(1 / XRatio) : ceil(1 / YRatio); + Ratio--; + Ratio |= Ratio >> 1; + Ratio |= Ratio >> 2; + Ratio++; + while(Ratio >>= 1) N++; + if(N > 3) { + ESP_LOGW(TAG, "Image will not fit %dx%d", Decoder.width, Decoder.height); + N = 3; + } + Context.Width /= 1 << N; + Context.Height /= 1 << N; + } + + // then place it + if(Fit & GDS_IMAGE_CENTER_X) + Context.XOfs = (Device->Width + x - Context.Width) / 2; + else if(Fit & GDS_IMAGE_RIGHT) + Context.XOfs = Device->Width - Context.Width; + if(Fit & GDS_IMAGE_CENTER_Y) + Context.YOfs = (Device->Height + y - Context.Height) / 2; + else if(Fit & GDS_IMAGE_BOTTOM) + Context.YOfs = Device->Height - Context.Height; + + Context.XMin = x - Context.XOfs; + Context.YMin = y - Context.YOfs; + Context.Mode = Device->Mode; + + // do decompress & draw + Res = jd_decomp(&Decoder, OutHandlerDirect, N); + if(Res == JDR_OK) { + Device->Dirty = true; + Ret = true; + } else { + ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", Res); + } + } else { ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", Res); - } - - // free scratch area - if (Scratch) free(Scratch); - return Ret; -} + } + // free scratch area + if(Scratch) free(Scratch); + return Ret; +} diff --git a/components/display/core/gds_image.h b/components/display/core/gds_image.h index ff0c3e6d..1c2e7e91 100644 --- a/components/display/core/gds_image.h +++ b/components/display/core/gds_image.h @@ -5,7 +5,7 @@ * https://opensource.org/licenses/MIT * */ - + #pragma once #include @@ -16,17 +16,17 @@ struct GDS_Device; // Fit options for GDS_DrawJPEG -#define GDS_IMAGE_LEFT 0x00 -#define GDS_IMAGE_CENTER_X 0x01 -#define GDS_IMAGE_RIGHT 0x04 -#define GDS_IMAGE_TOP 0x00 -#define GDS_IMAGE_BOTTOM 0x08 -#define GDS_IMAGE_CENTER_Y 0x02 -#define GDS_IMAGE_CENTER (GDS_IMAGE_CENTER_X | GDS_IMAGE_CENTER_Y) -#define GDS_IMAGE_FIT 0x10 // re-scale by a factor of 2^N (up to 3) +#define GDS_IMAGE_LEFT 0x00 +#define GDS_IMAGE_CENTER_X 0x01 +#define GDS_IMAGE_RIGHT 0x04 +#define GDS_IMAGE_TOP 0x00 +#define GDS_IMAGE_BOTTOM 0x08 +#define GDS_IMAGE_CENTER_Y 0x02 +#define GDS_IMAGE_CENTER (GDS_IMAGE_CENTER_X | GDS_IMAGE_CENTER_Y) +#define GDS_IMAGE_FIT 0x10 // re-scale by a factor of 2^N (up to 3) // Width and Height can be NULL if you already know them (actual scaling is closest ^2) -void* GDS_DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, int RGB_Mode); // can be 8, 16 or 24 bits per pixel in return -void GDS_GetJPEGSize(uint8_t *Source, int *Width, int *Height); -bool GDS_DrawJPEG( struct GDS_Device* Device, uint8_t *Source, int x, int y, int Fit); -void GDS_DrawRGB( struct GDS_Device* Device, uint8_t *Image, int x, int y, int Width, int Height, int RGB_Mode ); +void* GDS_DecodeJPEG(uint8_t* Source, int* Width, int* Height, float Scale, int RGB_Mode); // can be 8, 16 or 24 bits per pixel in return +void GDS_GetJPEGSize(uint8_t* Source, int* Width, int* Height); +bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t* Source, int x, int y, int Fit); +void GDS_DrawRGB(struct GDS_Device* Device, uint8_t* Image, int x, int y, int Width, int Height, int RGB_Mode); diff --git a/components/display/core/gds_private.h b/components/display/core/gds_private.h index c25dd4d9..21cc0d3e 100644 --- a/components/display/core/gds_private.h +++ b/components/display/core/gds_private.h @@ -5,7 +5,7 @@ * https://opensource.org/licenses/MIT * */ - + #ifndef _GDS_PRIVATE_H_ #define _GDS_PRIVATE_H_ @@ -15,44 +15,43 @@ #include "gds.h" #include "gds_err.h" -#define GDS_ALLOC_NONE 0x80 -#define GDS_ALLOC_IRAM 0x01 -#define GDS_ALLOC_IRAM_SPI 0x02 +#define GDS_ALLOC_NONE 0x80 +#define GDS_ALLOC_IRAM 0x01 +#define GDS_ALLOC_IRAM_SPI 0x02 #define GDS_CLIPDEBUG_NONE 0 #define GDS_CLIPDEBUG_WARNING 1 #define GDS_CLIPDEBUG_ERROR 2 #if CONFIG_GDS_CLIPDEBUG == GDS_CLIPDEBUG_NONE - /* +/* * Clip silently with no console output. */ - #define ClipDebug( x, y ) +#define ClipDebug(x, y) #elif CONFIG_GDS_CLIPDEBUG == GDS_CLIPDEBUG_WARNING - /* +/* * Log clipping to the console as a warning. */ - #define ClipDebug( x, y ) { \ - ESP_LOGW( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED", __LINE__, x, y ); \ - } +#define ClipDebug(x, y) \ + { ESP_LOGW(__FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED", __LINE__, x, y); } #elif CONFIG_GDS_CLIPDEBUG == GDS_CLIPDEBUG_ERROR - /* +/* * Log clipping as an error to the console. * Also invokes an abort with stack trace. */ - #define ClipDebug( x, y ) { \ - ESP_LOGE( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED, ABORT", __LINE__, x, y ); \ - abort( ); \ +#define ClipDebug(x, y) \ + { \ + ESP_LOGE(__FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED, ABORT", __LINE__, x, y); \ + abort(); \ } #endif +#define GDS_ALWAYS_INLINE __attribute__((always_inline)) -#define GDS_ALWAYS_INLINE __attribute__( ( always_inline ) ) +#define MAX_LINES 8 -#define MAX_LINES 8 - -#if ! defined BIT -#define BIT( n ) ( 1 << ( n ) ) +#if !defined BIT +#define BIT(n) (1 << (n)) #endif struct GDS_Device; @@ -61,102 +60,95 @@ struct GDS_FontDef; /* * These can optionally return a succeed/fail but are as of yet unused in the driver. */ -typedef bool ( *WriteCommandProc ) ( struct GDS_Device* Device, uint8_t Command ); -typedef bool ( *WriteDataProc ) ( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); +typedef bool (*WriteCommandProc)(struct GDS_Device* Device, uint8_t Command); +typedef bool (*WriteDataProc)(struct GDS_Device* Device, const uint8_t* Data, size_t DataLength); struct spi_device_t; typedef struct spi_device_t* spi_device_handle_t; -#define GDS_IF_SPI 0 -#define GDS_IF_I2C 1 +#define GDS_IF_SPI 0 +#define GDS_IF_I2C 1 struct GDS_Device { - uint8_t IF; - int8_t RSTPin; - struct { - int8_t Pin, Channel; - int PWM; - } Backlight; - union { - // I2C Specific - struct { - uint8_t Address; - }; - // SPI specific - struct { - spi_device_handle_t SPIHandle; - int8_t CSPin; - }; - }; - - // cooked text mode - struct { - int16_t Y, Space; - const struct GDS_FontDef* Font; - } Lines[MAX_LINES]; - - uint16_t Width, TextWidth; - uint16_t Height; - uint8_t Depth, Mode; - - uint8_t Alloc; - uint8_t* Framebuffer; - uint32_t FramebufferSize; - bool Dirty; + uint8_t IF; + int8_t RSTPin; + struct { + int8_t Pin, Channel; + int PWM; + } Backlight; + union { + // I2C Specific + struct { + uint8_t Address; + }; + // SPI specific + struct { + spi_device_handle_t SPIHandle; + int8_t CSPin; + }; + }; - // default fonts when using direct draw - const struct GDS_FontDef* Font; + // cooked text mode + struct { + int16_t Y, Space; + const struct GDS_FontDef* Font; + } Lines[MAX_LINES]; + + uint16_t Width, TextWidth; + uint16_t Height; + uint8_t Depth, Mode; + + uint8_t Alloc; + uint8_t* Framebuffer; + uint32_t FramebufferSize; + bool Dirty; + + // default fonts when using direct draw + const struct GDS_FontDef* Font; bool FontForceProportional; bool FontForceMonospace; - // various driver-specific method - // must always provide - bool (*Init)( struct GDS_Device* Device); - void (*Update)( struct GDS_Device* Device ); - // may provide if supported - void (*SetContrast)( struct GDS_Device* Device, uint8_t Contrast ); - void (*DisplayOn)( struct GDS_Device* Device ); - void (*DisplayOff)( struct GDS_Device* Device ); - void (*SetLayout)( struct GDS_Device* Device, struct GDS_Layout *Layout ); - // must provide for depth other than 1 (vertical) and 4 (may provide for optimization) - void (*DrawPixelFast)( struct GDS_Device* Device, int X, int Y, int Color ); - void (*DrawBitmapCBR)(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ); - // may provide for optimization - void (*DrawRGB)( struct GDS_Device* Device, uint8_t *Image,int x, int y, int Width, int Height, int RGB_Mode ); - void (*ClearWindow)( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ); - // may provide for tweaking - void (*SPIParams)(int Speed, uint8_t *mode, uint16_t *CS_pre, uint8_t *CS_post); - - // interface-specific methods + // various driver-specific method + // must always provide + bool (*Init)(struct GDS_Device* Device); + void (*Update)(struct GDS_Device* Device); + // may provide if supported + void (*SetContrast)(struct GDS_Device* Device, uint8_t Contrast); + void (*DisplayOn)(struct GDS_Device* Device); + void (*DisplayOff)(struct GDS_Device* Device); + void (*SetLayout)(struct GDS_Device* Device, struct GDS_Layout* Layout); + // must provide for depth other than 1 (vertical) and 4 (may provide for optimization) + void (*DrawPixelFast)(struct GDS_Device* Device, int X, int Y, int Color); + void (*DrawBitmapCBR)(struct GDS_Device* Device, uint8_t* Data, int Width, int Height, int Color); + // may provide for optimization + void (*DrawRGB)(struct GDS_Device* Device, uint8_t* Image, int x, int y, int Width, int Height, int RGB_Mode); + void (*ClearWindow)(struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color); + // may provide for tweaking + void (*SPIParams)(int Speed, uint8_t* mode, uint16_t* CS_pre, uint8_t* CS_post); + + // interface-specific methods WriteCommandProc WriteCommand; WriteDataProc WriteData; - // 32 bytes for whatever the driver wants (should be aligned as it's 32 bits) - uint32_t Private[8]; + // 32 bytes for whatever the driver wants (should be aligned as it's 32 bits) + uint32_t Private[8]; }; -bool GDS_Reset( struct GDS_Device* Device ); -bool GDS_Init( struct GDS_Device* Device ); +bool GDS_Reset(struct GDS_Device* Device); +bool GDS_Init(struct GDS_Device* Device); -static inline bool IsPixelVisible( struct GDS_Device* Device, int x, int y ) { - bool Result = ( - ( x >= 0 ) && - ( x < Device->Width ) && - ( y >= 0 ) && - ( y < Device->Height ) - ) ? true : false; +static inline bool IsPixelVisible(struct GDS_Device* Device, int x, int y) { + bool Result = ((x >= 0) && (x < Device->Width) && (y >= 0) && (y < Device->Height)) ? true : false; #if CONFIG_GDS_CLIPDEBUG > 0 - if ( Result == false ) { - ClipDebug( x, y ); - } + if(Result == false) { ClipDebug(x, y); } #endif return Result; } -static inline void DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - uint32_t YBit = ( Y & 0x07 ); +static inline void DrawPixel1Fast(struct GDS_Device* Device, int X, int Y, int Color) { + uint32_t YBit = (Y & 0x07); uint8_t* FBOffset; /* @@ -165,60 +157,67 @@ static inline void DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int * Dividing Y by 8 gives us which row the pixel is in but not * the bit position. */ - Y>>= 3; + Y >>= 3; - FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X ); + FBOffset = Device->Framebuffer + ((Y * Device->Width) + X); - if ( Color == GDS_COLOR_XOR ) { - *FBOffset ^= BIT( YBit ); + if(Color == GDS_COLOR_XOR) { + *FBOffset ^= BIT(YBit); } else { - *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( YBit ) : *FBOffset | BIT( YBit ); + *FBOffset = (Color == GDS_COLOR_BLACK) ? *FBOffset & ~BIT(YBit) : *FBOffset | BIT(YBit); } } -static inline void DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1)); - *FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f)); +static inline void DrawPixel4Fast(struct GDS_Device* Device, int X, int Y, int Color) { + uint8_t* FBOffset = Device->Framebuffer + ((Y * Device->Width >> 1) + (X >> 1)); + *FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f)); } -static inline void DrawPixel8Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - Device->Framebuffer[Y * Device->Width + X] = Color; -} +static inline void DrawPixel8Fast(struct GDS_Device* Device, int X, int Y, int Color) { Device->Framebuffer[Y * Device->Width + X] = Color; } // assumes that Color is 16 bits R..RG..GB..B from MSB to LSB and FB wants 1st serialized byte to start with R -static inline void DrawPixel16Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - uint16_t* FBOffset = (uint16_t*) Device->Framebuffer + Y * Device->Width + X; - *FBOffset = __builtin_bswap16(Color); +static inline void DrawPixel16Fast(struct GDS_Device* Device, int X, int Y, int Color) { + uint16_t* FBOffset = (uint16_t*)Device->Framebuffer + Y * Device->Width + X; + *FBOffset = __builtin_bswap16(Color); } -// assumes that Color is 18 bits RGB from MSB to LSB RRRRRRGGGGGGBBBBBB, so byte[0] is B -// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = xxRRRRRR xxGGGGGG xxBBBBBB -static inline void DrawPixel18Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3; - *FBOffset++ = Color >> 12; *FBOffset++ = (Color >> 6) & 0x3f; *FBOffset = Color & 0x3f; +// assumes that Color is 18 bits RGB from MSB to LSB RRRRRRGGGGGGBBBBBB, so byte[0] is B +// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = xxRRRRRR xxGGGGGG xxBBBBBB +static inline void DrawPixel18Fast(struct GDS_Device* Device, int X, int Y, int Color) { + uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3; + *FBOffset++ = Color >> 12; + *FBOffset++ = (Color >> 6) & 0x3f; + *FBOffset = Color & 0x3f; } -// assumes that Color is 24 bits RGB from MSB to LSB RRRRRRRRGGGGGGGGBBBBBBBB, so byte[0] is B -// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = RRRRRRRR GGGGGGGG BBBBBBBB -static inline void DrawPixel24Fast( struct GDS_Device* Device, int X, int Y, int Color ) { - uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3; - *FBOffset++ = Color >> 16; *FBOffset++ = Color >> 8; *FBOffset = Color; +// assumes that Color is 24 bits RGB from MSB to LSB RRRRRRRRGGGGGGGGBBBBBBBB, so byte[0] is B +// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = RRRRRRRR GGGGGGGG BBBBBBBB +static inline void DrawPixel24Fast(struct GDS_Device* Device, int X, int Y, int Color) { + uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3; + *FBOffset++ = Color >> 16; + *FBOffset++ = Color >> 8; + *FBOffset = Color; } -static inline void IRAM_ATTR DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) { - if (Device->DrawPixelFast) Device->DrawPixelFast( Device, X, Y, Color ); - else if (Device->Depth == 4) DrawPixel4Fast( Device, X, Y, Color ); - else if (Device->Depth == 1) DrawPixel1Fast( Device, X, Y, Color ); - else if (Device->Depth == 16) DrawPixel16Fast( Device, X, Y, Color ); - else if (Device->Depth == 24 && Device->Mode == GDS_RGB666) DrawPixel18Fast( Device, X, Y, Color ); - else if (Device->Depth == 24 && Device->Mode == GDS_RGB888) DrawPixel24Fast( Device, X, Y, Color ); - else if (Device->Depth == 8) DrawPixel8Fast( Device, X, Y, Color ); -} +static inline void IRAM_ATTR DrawPixelFast(struct GDS_Device* Device, int X, int Y, int Color) { + if(Device->DrawPixelFast) + Device->DrawPixelFast(Device, X, Y, Color); + else if(Device->Depth == 4) + DrawPixel4Fast(Device, X, Y, Color); + else if(Device->Depth == 1) + DrawPixel1Fast(Device, X, Y, Color); + else if(Device->Depth == 16) + DrawPixel16Fast(Device, X, Y, Color); + else if(Device->Depth == 24 && Device->Mode == GDS_RGB666) + DrawPixel18Fast(Device, X, Y, Color); + else if(Device->Depth == 24 && Device->Mode == GDS_RGB888) + DrawPixel24Fast(Device, X, Y, Color); + else if(Device->Depth == 8) + DrawPixel8Fast(Device, X, Y, Color); +} -static inline void IRAM_ATTR DrawPixel( struct GDS_Device* Device, int x, int y, int Color ) { - if ( IsPixelVisible( Device, x, y ) == true ) { - DrawPixelFast( Device, x, y, Color ); - } +static inline void IRAM_ATTR DrawPixel(struct GDS_Device* Device, int x, int y, int Color) { + if(IsPixelVisible(Device, x, y) == true) { DrawPixelFast(Device, x, y, Color); } } #endif \ No newline at end of file diff --git a/components/display/core/gds_text.c b/components/display/core/gds_text.c index aa09d162..0423eeed 100644 --- a/components/display/core/gds_text.c +++ b/components/display/core/gds_text.c @@ -17,191 +17,193 @@ #include "gds_draw.h" #include "gds_text.h" -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) static char TAG[] = "gds"; /**************************************************************************************** * Set fonts for each line in text mode */ -static const struct GDS_FontDef *GuessFont( struct GDS_Device *Device, int FontType) { - switch(FontType) { - case GDS_FONT_DEFAULT: - return Device->Font; - case GDS_FONT_LINE_1: - return Font_line_1; - case GDS_FONT_LINE_2: - return Font_line_2; - case GDS_FONT_MEDIUM: - //return &Font_droid_sans_fallback_15x17; - case GDS_FONT_SMALL: - default: - return Font_droid_sans_fallback_11x13; +static const struct GDS_FontDef* GuessFont(struct GDS_Device* Device, int FontType) { + switch(FontType) { + case GDS_FONT_DEFAULT: + return Device->Font; + case GDS_FONT_LINE_1: + return Font_line_1; + case GDS_FONT_LINE_2: + return Font_line_2; + case GDS_FONT_MEDIUM: + //return &Font_droid_sans_fallback_15x17; + case GDS_FONT_SMALL: + default: + return Font_droid_sans_fallback_11x13; #ifdef USE_LARGE_FONTS - case GDS_FONT_LARGE: - return &Font_droid_sans_fallback_24x28; - case GDS_FONT_SEGMENT: - if (Device->Height == 32) return &Font_Tarable7Seg_16x32; - else return &Font_Tarable7Seg_32x64; + case GDS_FONT_LARGE: + return &Font_droid_sans_fallback_24x28; + case GDS_FONT_SEGMENT: + if(Device->Height == 32) + return &Font_Tarable7Seg_16x32; + else + return &Font_Tarable7Seg_32x64; #else - case GDS_FONT_LARGE: - case GDS_FONT_SEGMENT: - ESP_LOGW(TAG, "large fonts disabled"); - //return &Font_droid_sans_fallback_15x17; - return Font_droid_sans_fallback_11x13; -#endif - } + case GDS_FONT_LARGE: + case GDS_FONT_SEGMENT: + ESP_LOGW(TAG, "large fonts disabled"); + //return &Font_droid_sans_fallback_15x17; + return Font_droid_sans_fallback_11x13; +#endif + } } - /**************************************************************************************** * Set fonts for each line in text mode */ bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space) { - const struct GDS_FontDef *Font = GuessFont( Device, FontType ); - return GDS_TextSetFont( Device, N, Font, Space ); + const struct GDS_FontDef* Font = GuessFont(Device, FontType); + return GDS_TextSetFont(Device, N, Font, Space); } /**************************************************************************************** * Set fonts for each line in text mode */ -bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space) { - if (--N >= MAX_LINES) return false; +bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef* Font, int Space) { + if(--N >= MAX_LINES) return false; - Device->Lines[N].Font = Font; - - // re-calculate lines absolute position - Device->Lines[N].Space = Space; - Device->Lines[0].Y = Device->Lines[0].Space; - for (int i = 1; i <= N; i++) Device->Lines[i].Y = Device->Lines[i-1].Y + Device->Lines[i-1].Font->Height + Device->Lines[i].Space; - - ESP_LOGI(TAG, "Adding line %u at %d (height:%u)", N + 1, Device->Lines[N].Y, Device->Lines[N].Font->Height); - - if (Device->Lines[N].Y + Device->Lines[N].Font->Height > Device->Height) { - ESP_LOGW(TAG, "line does not fit display"); - return false; - } - - return true; + Device->Lines[N].Font = Font; + + // re-calculate lines absolute position + Device->Lines[N].Space = Space; + Device->Lines[0].Y = Device->Lines[0].Space; + for(int i = 1; i <= N; i++) Device->Lines[i].Y = Device->Lines[i - 1].Y + Device->Lines[i - 1].Font->Height + Device->Lines[i].Space; + + ESP_LOGI(TAG, "Adding line %u at %d (height:%u)", N + 1, Device->Lines[N].Y, Device->Lines[N].Font->Height); + + if(Device->Lines[N].Y + Device->Lines[N].Font->Height > Device->Height) { + ESP_LOGW(TAG, "line does not fit display"); + return false; + } + + return true; } /**************************************************************************************** * */ -bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text) { - int Width, X = Pos; +bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char* Text) { + int Width, X = Pos; - // counting 1..n - N--; - - GDS_SetFont( Device, Device->Lines[N].Font ); - if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true ); - - Width = GDS_FontMeasureString( Device, Text ); - - // adjusting position, erase only EoL for rigth-justified - if (Pos == GDS_TEXT_RIGHT) X = Device->TextWidth - Width - 1; - else if (Pos == GDS_TEXT_CENTER) X = (Device->TextWidth - Width) / 2; - - // erase if requested - if (Attr & GDS_TEXT_CLEAR) { - int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height); - for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->TextWidth; c++) - for (int y = Y_min; y < Y_max; y++) - DrawPixelFast( Device, c, y, GDS_COLOR_BLACK ); - } - - GDS_FontDrawString( Device, X, Device->Lines[N].Y, Text, GDS_COLOR_WHITE ); - - ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", Text, N+1, X, Attr); - - // update whole display if requested - Device->Dirty = true; - if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device ); - - return Width + X < Device->TextWidth; + // counting 1..n + N--; + + GDS_SetFont(Device, Device->Lines[N].Font); + if(Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace(Device, true); + + Width = GDS_FontMeasureString(Device, Text); + + // adjusting position, erase only EoL for rigth-justified + if(Pos == GDS_TEXT_RIGHT) + X = Device->TextWidth - Width - 1; + else if(Pos == GDS_TEXT_CENTER) + X = (Device->TextWidth - Width) / 2; + + // erase if requested + if(Attr & GDS_TEXT_CLEAR) { + int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height); + for(int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->TextWidth; c++) + for(int y = Y_min; y < Y_max; y++) DrawPixelFast(Device, c, y, GDS_COLOR_BLACK); + } + + GDS_FontDrawString(Device, X, Device->Lines[N].Y, Text, GDS_COLOR_WHITE); + + ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", Text, N + 1, X, Attr); + + // update whole display if requested + Device->Dirty = true; + if(Attr & GDS_TEXT_UPDATE) GDS_Update(Device); + + return Width + X < Device->TextWidth; } /**************************************************************************************** * */ -int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text) { - const struct GDS_FontDef *Font = GDS_SetFont( Device, Device->Lines[N-1].Font ); +int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char* Text) { + const struct GDS_FontDef* Font = GDS_SetFont(Device, Device->Lines[N - 1].Font); - if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true ); - int Width = GDS_FontMeasureString( Device, Text ); - GDS_SetFont( Device, Font ); + if(Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace(Device, true); + int Width = GDS_FontMeasureString(Device, Text); + GDS_SetFont(Device, Font); - return Width; + return Width; } /**************************************************************************************** * Try to align string for better scrolling visual. there is probably much better to do */ -int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) { - char Space[] = " "; - int Len = strlen(String), Extra = 0, Boundary; - - N--; - - // we might already fit - GDS_SetFont( Device, Device->Lines[N].Font ); - if (GDS_FontMeasureString( Device, String ) <= Device->TextWidth) return 0; - - // add some space for better visual - strncat(String, Space, Max-Len); - String[Max] = '\0'; - Len = strlen(String); - - // mark the end of the extended string - Boundary = GDS_FontMeasureString( Device, String ); - - // add a full display width - while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->TextWidth) { - String[Len++] = String[Extra++]; - String[Len] = '\0'; - } - - return Boundary; +int GDS_TextStretch(struct GDS_Device* Device, int N, char* String, int Max) { + char Space[] = " "; + int Len = strlen(String), Extra = 0, Boundary; + + N--; + + // we might already fit + GDS_SetFont(Device, Device->Lines[N].Font); + if(GDS_FontMeasureString(Device, String) <= Device->TextWidth) return 0; + + // add some space for better visual + strncat(String, Space, Max - Len); + String[Max] = '\0'; + Len = strlen(String); + + // mark the end of the extended string + Boundary = GDS_FontMeasureString(Device, String); + + // add a full display width + while(Len < Max && GDS_FontMeasureString(Device, String) - Boundary < Device->TextWidth) { + String[Len++] = String[Extra++]; + String[Len] = '\0'; + } + + return Boundary; } /**************************************************************************************** * */ -void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...) { - va_list args; +void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char* Text, ...) { + va_list args; - TextAnchor Anchor = TextAnchor_Center; - - if (Attr & GDS_TEXT_CLEAR) GDS_Clear( Device, GDS_COLOR_BLACK ); - - if (!Text) return; - - va_start(args, Text); - - switch(Where) { - case GDS_TEXT_TOP_LEFT: - default: - Anchor = TextAnchor_NorthWest; - break; - case GDS_TEXT_MIDDLE_LEFT: - Anchor = TextAnchor_West; - break; - case GDS_TEXT_BOTTOM_LEFT: - Anchor = TextAnchor_SouthWest; - break; - case GDS_TEXT_CENTERED: - Anchor = TextAnchor_Center; - break; - } - - ESP_LOGD(TAG, "Displaying %s at %u with attribute %u", Text, Anchor, Attr); - - GDS_SetFont( Device, GuessFont( Device, FontType ) ); - GDS_FontDrawAnchoredString( Device, Anchor, Text, GDS_COLOR_WHITE ); - - Device->Dirty = true; - if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device ); - - va_end(args); + TextAnchor Anchor = TextAnchor_Center; + + if(Attr & GDS_TEXT_CLEAR) GDS_Clear(Device, GDS_COLOR_BLACK); + + if(!Text) return; + + va_start(args, Text); + + switch(Where) { + case GDS_TEXT_TOP_LEFT: + default: + Anchor = TextAnchor_NorthWest; + break; + case GDS_TEXT_MIDDLE_LEFT: + Anchor = TextAnchor_West; + break; + case GDS_TEXT_BOTTOM_LEFT: + Anchor = TextAnchor_SouthWest; + break; + case GDS_TEXT_CENTERED: + Anchor = TextAnchor_Center; + break; + } + + ESP_LOGD(TAG, "Displaying %s at %u with attribute %u", Text, Anchor, Attr); + + GDS_SetFont(Device, GuessFont(Device, FontType)); + GDS_FontDrawAnchoredString(Device, Anchor, Text, GDS_COLOR_WHITE); + + Device->Dirty = true; + if(Attr & GDS_TEXT_UPDATE) GDS_Update(Device); + + va_end(args); } diff --git a/components/display/core/gds_text.h b/components/display/core/gds_text.h index 80d1a995..bffa008b 100644 --- a/components/display/core/gds_text.h +++ b/components/display/core/gds_text.h @@ -10,27 +10,36 @@ #include "gds_font.h" -#define GDS_TEXT_CLEAR 0x01 -#define GDS_TEXT_CLEAR_EOL 0x02 -#define GDS_TEXT_UPDATE 0x04 -#define GDS_TEXT_MONOSPACE 0x08 +#define GDS_TEXT_CLEAR 0x01 +#define GDS_TEXT_CLEAR_EOL 0x02 +#define GDS_TEXT_UPDATE 0x04 +#define GDS_TEXT_MONOSPACE 0x08 // these ones are for 'Pos' parameter of TextLine -#define GDS_TEXT_LEFT 0 -#define GDS_TEXT_RIGHT 0xff00 -#define GDS_TEXT_CENTER 0xff01 +#define GDS_TEXT_LEFT 0 +#define GDS_TEXT_RIGHT 0xff00 +#define GDS_TEXT_CENTER 0xff01 // these ones are for the 'Where' parameter of TextPos enum { GDS_TEXT_TOP_LEFT, GDS_TEXT_MIDDLE_LEFT, GDS_TEXT_BOTTOM_LEFT, GDS_TEXT_CENTERED }; -enum { GDS_FONT_DEFAULT, GDS_FONT_LINE_1, GDS_FONT_LINE_2, GDS_FONT_SEGMENT, - GDS_FONT_TINY, GDS_FONT_SMALL, GDS_FONT_MEDIUM, GDS_FONT_LARGE, GDS_FONT_FONT_HUGE }; - +enum { + GDS_FONT_DEFAULT, + GDS_FONT_LINE_1, + GDS_FONT_LINE_2, + GDS_FONT_SEGMENT, + GDS_FONT_TINY, + GDS_FONT_SMALL, + GDS_FONT_MEDIUM, + GDS_FONT_LARGE, + GDS_FONT_FONT_HUGE +}; + struct GDS_Device; - -bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space); -bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space); -bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text); -int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text); -int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max); -void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...); \ No newline at end of file + +bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space); +bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef* Font, int Space); +bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char* Text); +int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char* Text); +int GDS_TextStretch(struct GDS_Device* Device, int N, char* String, int Max); +void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char* Text, ...); \ No newline at end of file diff --git a/components/display/core/ifaces/default_if_i2c.c b/components/display/core/ifaces/default_if_i2c.c index 22f5934e..85637dc3 100644 --- a/components/display/core/ifaces/default_if_i2c.c +++ b/components/display/core/ifaces/default_if_i2c.c @@ -22,9 +22,9 @@ static int I2CWait; static const int GDS_I2C_COMMAND_MODE = 0x80; static const int GDS_I2C_DATA_MODE = 0x40; -static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength ); -static bool I2CDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ); -static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); +static bool I2CDefaultWriteBytes(int Address, bool IsCommand, const uint8_t* Data, size_t DataLength); +static bool I2CDefaultWriteCommand(struct GDS_Device* Device, uint8_t Command); +static bool I2CDefaultWriteData(struct GDS_Device* Device, const uint8_t* Data, size_t DataLength); /* * Initializes the i2c master with the parameters specified @@ -32,24 +32,24 @@ static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, * * Returns true on successful init of the i2c bus. */ -bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int Speed ) { - I2CPortNumber = PortNumber; - - I2CWait = pdMS_TO_TICKS( Speed ? (250 * 250000) / Speed : 250 ); - - if (SDA != -1 && SCL != -1) { - i2c_config_t Config = { 0 }; +bool GDS_I2CInit(int PortNumber, int SDA, int SCL, int Speed) { + I2CPortNumber = PortNumber; + + I2CWait = pdMS_TO_TICKS(Speed ? (250 * 250000) / Speed : 250); + + if(SDA != -1 && SCL != -1) { + i2c_config_t Config = {0}; Config.mode = I2C_MODE_MASTER; - Config.sda_io_num = SDA; - Config.sda_pullup_en = GPIO_PULLUP_ENABLE; - Config.scl_io_num = SCL; - Config.scl_pullup_en = GPIO_PULLUP_ENABLE; - Config.master.clk_speed = Speed ? Speed : 400000; + Config.sda_io_num = SDA; + Config.sda_pullup_en = GPIO_PULLUP_ENABLE; + Config.scl_io_num = SCL; + Config.scl_pullup_en = GPIO_PULLUP_ENABLE; + Config.master.clk_speed = Speed ? Speed : 400000; - ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false ); - ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false ); - } + ESP_ERROR_CHECK_NONFATAL(i2c_param_config(I2CPortNumber, &Config), return false); + ESP_ERROR_CHECK_NONFATAL(i2c_driver_install(I2CPortNumber, Config.mode, 0, 0, 0), return false); + } return true; } @@ -66,63 +66,63 @@ bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int Speed ) { * * Returns true on successful init of display. */ -bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin, int BacklightPin ) { - NullCheck( Device, return false ); +bool GDS_I2CAttachDevice(struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin, int BacklightPin) { + NullCheck(Device, return false); Device->WriteCommand = I2CDefaultWriteCommand; Device->WriteData = I2CDefaultWriteData; Device->Address = I2CAddress; Device->RSTPin = RSTPin; - Device->Backlight.Pin = BacklightPin; - Device->IF = GDS_IF_I2C; - Device->Width = Device->TextWidth = Width; - Device->Height = Height; - - if ( RSTPin >= 0 ) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 1 ), return false ); - GDS_Reset( Device ); + Device->Backlight.Pin = BacklightPin; + Device->IF = GDS_IF_I2C; + Device->Width = Device->TextWidth = Width; + Device->Height = Height; + + if(RSTPin >= 0) { + ESP_ERROR_CHECK_NONFATAL(gpio_set_direction(RSTPin, GPIO_MODE_OUTPUT), return false); + ESP_ERROR_CHECK_NONFATAL(gpio_set_level(RSTPin, 1), return false); + GDS_Reset(Device); } - - return GDS_Init( Device ); + + return GDS_Init(Device); } -static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength ) { +static bool I2CDefaultWriteBytes(int Address, bool IsCommand, const uint8_t* Data, size_t DataLength) { i2c_cmd_handle_t* CommandHandle = NULL; static uint8_t ModeByte = 0; - NullCheck( Data, return false ); + NullCheck(Data, return false); - if ( ( CommandHandle = i2c_cmd_link_create( ) ) != NULL ) { - ModeByte = ( IsCommand == true ) ? GDS_I2C_COMMAND_MODE: GDS_I2C_DATA_MODE; + if((CommandHandle = i2c_cmd_link_create()) != NULL) { + ModeByte = (IsCommand == true) ? GDS_I2C_COMMAND_MODE : GDS_I2C_DATA_MODE; - ESP_ERROR_CHECK_NONFATAL( i2c_master_start( CommandHandle ), goto error ); - ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ( Address << 1 ) | I2C_MASTER_WRITE, true ), goto error ); - ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ModeByte, true ), goto error ); - ESP_ERROR_CHECK_NONFATAL( i2c_master_write( CommandHandle, ( uint8_t* ) Data, DataLength, true ), goto error ); - ESP_ERROR_CHECK_NONFATAL( i2c_master_stop( CommandHandle ), goto error ); + ESP_ERROR_CHECK_NONFATAL(i2c_master_start(CommandHandle), goto error); + ESP_ERROR_CHECK_NONFATAL(i2c_master_write_byte(CommandHandle, (Address << 1) | I2C_MASTER_WRITE, true), goto error); + ESP_ERROR_CHECK_NONFATAL(i2c_master_write_byte(CommandHandle, ModeByte, true), goto error); + ESP_ERROR_CHECK_NONFATAL(i2c_master_write(CommandHandle, (uint8_t*)Data, DataLength, true), goto error); + ESP_ERROR_CHECK_NONFATAL(i2c_master_stop(CommandHandle), goto error); - ESP_ERROR_CHECK_NONFATAL( i2c_master_cmd_begin( I2CPortNumber, CommandHandle, I2CWait ), goto error ); - i2c_cmd_link_delete( CommandHandle ); + ESP_ERROR_CHECK_NONFATAL(i2c_master_cmd_begin(I2CPortNumber, CommandHandle, I2CWait), goto error); + i2c_cmd_link_delete(CommandHandle); } return true; - + error: - if (CommandHandle) i2c_cmd_link_delete( CommandHandle ); - return false; + if(CommandHandle) i2c_cmd_link_delete(CommandHandle); + return false; } -static bool I2CDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ) { - uint8_t CommandByte = ( uint8_t ) Command; - - NullCheck( Device, return false ); - return I2CDefaultWriteBytes( Device->Address, true, ( const uint8_t* ) &CommandByte, 1 ); +static bool I2CDefaultWriteCommand(struct GDS_Device* Device, uint8_t Command) { + uint8_t CommandByte = (uint8_t)Command; + + NullCheck(Device, return false); + return I2CDefaultWriteBytes(Device->Address, true, (const uint8_t*)&CommandByte, 1); } -static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ) { - NullCheck( Device, return false ); - NullCheck( Data, return false ); +static bool I2CDefaultWriteData(struct GDS_Device* Device, const uint8_t* Data, size_t DataLength) { + NullCheck(Device, return false); + NullCheck(Data, return false); - return I2CDefaultWriteBytes( Device->Address, false, Data, DataLength ); + return I2CDefaultWriteBytes(Device->Address, false, Data, DataLength); } diff --git a/components/display/core/ifaces/default_if_spi.c b/components/display/core/ifaces/default_if_spi.c index b561c297..bfcc69e4 100644 --- a/components/display/core/ifaces/default_if_spi.c +++ b/components/display/core/ifaces/default_if_spi.c @@ -24,96 +24,98 @@ static const int GDS_SPI_Data_Mode = 1; static spi_host_device_t SPIHost; static int DCPin; -static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ); -static bool SPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ); -static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); +static bool SPIDefaultWriteBytes(spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength); +static bool SPIDefaultWriteCommand(struct GDS_Device* Device, uint8_t Command); +static bool SPIDefaultWriteData(struct GDS_Device* Device, const uint8_t* Data, size_t DataLength); -bool GDS_SPIInit( int SPI, int DC ) { - SPIHost = SPI; - DCPin = DC; +bool GDS_SPIInit(int SPI, int DC) { + SPIHost = SPI; + DCPin = DC; return true; } -bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed, int Mode ) { - spi_device_interface_config_t SPIDeviceConfig = { }; +bool GDS_SPIAttachDevice(struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed, int Mode) { + spi_device_interface_config_t SPIDeviceConfig = {}; spi_device_handle_t SPIDevice; - NullCheck( Device, return false ); - - if (CSPin >= 0) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false ); - } - + NullCheck(Device, return false); + + if(CSPin >= 0) { + ESP_ERROR_CHECK_NONFATAL(gpio_set_direction(CSPin, GPIO_MODE_OUTPUT), return false); + ESP_ERROR_CHECK_NONFATAL(gpio_set_level(CSPin, 0), return false); + } + SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M; SPIDeviceConfig.spics_io_num = CSPin; SPIDeviceConfig.queue_size = 1; SPIDeviceConfig.mode = Mode; - SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY; - if (Device->SPIParams) Device->SPIParams(SPIDeviceConfig.clock_speed_hz, &SPIDeviceConfig.mode, - &SPIDeviceConfig.cs_ena_pretrans, &SPIDeviceConfig.cs_ena_posttrans); - - ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDevice ), return false ); - - Device->WriteCommand = SPIDefaultWriteCommand; + SPIDeviceConfig.flags = SPI_DEVICE_NO_DUMMY; + if(Device->SPIParams) + Device->SPIParams(SPIDeviceConfig.clock_speed_hz, &SPIDeviceConfig.mode, &SPIDeviceConfig.cs_ena_pretrans, &SPIDeviceConfig.cs_ena_posttrans); + + ESP_ERROR_CHECK_NONFATAL(spi_bus_add_device(SPIHost, &SPIDeviceConfig, &SPIDevice), return false); + + Device->WriteCommand = SPIDefaultWriteCommand; Device->WriteData = SPIDefaultWriteData; Device->SPIHandle = SPIDevice; Device->RSTPin = RSTPin; Device->CSPin = CSPin; - Device->Backlight.Pin = BackLightPin; - Device->IF = GDS_IF_SPI; - Device->Width = Device->TextWidth = Width; - Device->Height = Height; - - if ( RSTPin >= 0 ) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 0 ), return false ); - GDS_Reset( Device ); + Device->Backlight.Pin = BackLightPin; + Device->IF = GDS_IF_SPI; + Device->Width = Device->TextWidth = Width; + Device->Height = Height; + + if(RSTPin >= 0) { + ESP_ERROR_CHECK_NONFATAL(gpio_set_direction(RSTPin, GPIO_MODE_OUTPUT), return false); + ESP_ERROR_CHECK_NONFATAL(gpio_set_level(RSTPin, 0), return false); + GDS_Reset(Device); } - - return GDS_Init( Device ); + + return GDS_Init(Device); } -static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) { - spi_transaction_t SPITransaction = { }; +static bool SPIDefaultWriteBytes(spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength) { + spi_transaction_t SPITransaction = {}; - NullCheck( SPIHandle, return false ); - NullCheck( Data, return false ); + NullCheck(SPIHandle, return false); + NullCheck(Data, return false); - if ( DataLength > 0 ) { - gpio_set_level( DCPin, WriteMode ); + if(DataLength > 0) { + gpio_set_level(DCPin, WriteMode); - SPITransaction.length = DataLength * 8; - - if (DataLength <= 4) { - SPITransaction.flags = SPI_TRANS_USE_TXDATA; - SPITransaction.tx_data[0] = *Data++; SPITransaction.tx_data[1] = *Data++; - SPITransaction.tx_data[2] = *Data++; SPITransaction.tx_data[3] = *Data; - } else { - SPITransaction.tx_buffer = Data; - } - - // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) - ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false ); + SPITransaction.length = DataLength * 8; + + if(DataLength <= 4) { + SPITransaction.flags = SPI_TRANS_USE_TXDATA; + SPITransaction.tx_data[0] = *Data++; + SPITransaction.tx_data[1] = *Data++; + SPITransaction.tx_data[2] = *Data++; + SPITransaction.tx_data[3] = *Data; + } else { + SPITransaction.tx_buffer = Data; + } + + // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) + ESP_ERROR_CHECK_NONFATAL(spi_device_polling_transmit(SPIHandle, &SPITransaction), return false); } return true; } -static bool SPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ) { +static bool SPIDefaultWriteCommand(struct GDS_Device* Device, uint8_t Command) { static uint8_t CommandByte = 0; - NullCheck( Device, return false ); - NullCheck( Device->SPIHandle, return false ); + NullCheck(Device, return false); + NullCheck(Device->SPIHandle, return false); CommandByte = Command; - return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Command_Mode, &CommandByte, 1 ); + return SPIDefaultWriteBytes(Device->SPIHandle, GDS_SPI_Command_Mode, &CommandByte, 1); } -static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ) { - NullCheck( Device, return false ); - NullCheck( Device->SPIHandle, return false ); +static bool SPIDefaultWriteData(struct GDS_Device* Device, const uint8_t* Data, size_t DataLength) { + NullCheck(Device, return false); + NullCheck(Device->SPIHandle, return false); - return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Data_Mode, Data, DataLength ); + return SPIDefaultWriteBytes(Device->SPIHandle, GDS_SPI_Data_Mode, Data, DataLength); } \ No newline at end of file diff --git a/components/display/display.c b/components/display/display.c index 55655f28..e80be16d 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -23,471 +23,468 @@ #include "gds_font.h" #include "gds_image.h" #include "Config.h" -static const char *TAG = "display"; +static const char* TAG = "display"; -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define DISPLAYER_STACK_SIZE (3*1024) -#define SCROLLABLE_SIZE 384 -#define HEADER_SIZE 64 -#define DEFAULT_SLEEP 3600 -#define ARTWORK_BORDER 1 +#define DISPLAYER_STACK_SIZE (3 * 1024) +#define SCROLLABLE_SIZE 384 +#define HEADER_SIZE 64 +#define DEFAULT_SLEEP 3600 +#define ARTWORK_BORDER 1 -extern const uint8_t default_artwork[] asm("_binary_note_jpg_start"); +extern const uint8_t default_artwork[] asm("_binary_note_jpg_start"); static EXT_RAM_ATTR struct { - TaskHandle_t task; - SemaphoreHandle_t mutex; - int pause, speed, by; - enum { DISPLAYER_DOWN, DISPLAYER_IDLE, DISPLAYER_ACTIVE } state; - char header[HEADER_SIZE + 1]; - char string[SCROLLABLE_SIZE + 1]; - int offset, boundary; - sys_metadata_config *metadata_config; - bool timer, refresh; - uint32_t elapsed; - struct { - uint32_t value; - char string[8]; // H:MM:SS - bool visible; - } duration; - struct { - bool enable, active; - bool fit; - bool updated; - int tick; - int offset; - } artwork; - TickType_t tick; + TaskHandle_t task; + SemaphoreHandle_t mutex; + int pause, speed, by; + enum { DISPLAYER_DOWN, DISPLAYER_IDLE, DISPLAYER_ACTIVE } state; + char header[HEADER_SIZE + 1]; + char string[SCROLLABLE_SIZE + 1]; + int offset, boundary; + sys_metadata_config* metadata_config; + bool timer, refresh; + uint32_t elapsed; + struct { + uint32_t value; + char string[8]; // H:MM:SS + bool visible; + } duration; + struct { + bool enable, active; + bool fit; + bool updated; + int tick; + int offset; + } artwork; + TickType_t tick; } displayer; - -static void displayer_task(void *args); +static void displayer_task(void* args); static void display_sleep(void); -struct GDS_Device *display; -bool (*display_bus)(void *from, enum display_bus_cmd_e cmd) = NULL; +struct GDS_Device* display; +bool (*display_bus)(void* from, enum display_bus_cmd_e cmd) = NULL; extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect; -GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect, NULL }; +GDS_DetectFunc* drivers[] = { + SH1106_Detect, SSD1306_Detect, SSD132x_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect, NULL}; /**************************************************************************************** * */ -void display_init(char *welcome) { - bool init = false; - int width = -1, height = -1, backlight_pin = -1, RST_pin = -1; - sys_display_config * sys_display; - sys_display_common * common; +void display_init(char* welcome) { + bool init = false; + int width = -1, height = -1, backlight_pin = -1, RST_pin = -1; + sys_display_config* sys_display; + sys_display_common* common; - if(!SYS_DISPLAY(sys_display) || !SYS_DISPLAY_COMMON(common) || common->driver == sys_display_drivers_UNSPECIFIED){ - ESP_LOGI(TAG,"No display configuration"); - return; - } - // // so far so good - if( common->width == 0 || common->height == 0){ - ESP_LOGE(TAG,"Misconfigured display missing data"); - return; - } - ESP_LOGI(TAG, "Initializing display type %s, driver: %s", - sys_dev_common_types_name(sys_display->type), - sys_display_drivers_name(common->driver)); - if (common->back >= 0) { - struct GDS_BacklightPWM PWMConfig = { .Channel = pwm_system.base_channel++, .Timer = pwm_system.timer, .Max = pwm_system.max, .Init = false }; - display = GDS_AutoDetect(sys_display, drivers, &PWMConfig); - } else { - display = GDS_AutoDetect(sys_display, drivers, NULL); - } + if(!SYS_DISPLAY(sys_display) || !SYS_DISPLAY_COMMON(common) || common->driver == sys_display_drivers_UNSPECIFIED) { + ESP_LOGI(TAG, "No display configuration"); + return; + } + // // so far so good + if(common->width == 0 || common->height == 0) { + ESP_LOGE(TAG, "Misconfigured display missing data"); + return; + } + ESP_LOGI(TAG, "Initializing display type %s, driver: %s", sys_dev_common_types_name(sys_display->type), sys_display_drivers_name(common->driver)); + if(common->back >= 0) { + struct GDS_BacklightPWM PWMConfig = {.Channel = pwm_system.base_channel++, .Timer = pwm_system.timer, .Max = pwm_system.max, .Init = false}; + display = GDS_AutoDetect(sys_display, drivers, &PWMConfig); + } else { + display = GDS_AutoDetect(sys_display, drivers, NULL); + } - if (display) { - RST_pin = common->reset; - backlight_pin = common->back; - width = common->width; - height = common->height; + if(display) { + RST_pin = common->reset; + backlight_pin = common->back; + width = common->width; + height = common->height; - // Detect driver interface - if (sys_display->which_dispType == sys_display_config_i2c_tag && platform->dev.i2c.port != sys_i2c_port_UNSPECIFIED){ - int address = 0x3C; - - address = sys_display->dispType.i2c.address; - init = true; - GDS_I2CInit( platform->dev.i2c.port-sys_i2c_port_PORT0, -1, -1, platform->dev.i2c.speed ) ; - GDS_I2CAttachDevice( display, width, height, address, RST_pin, backlight_pin ); - - ESP_LOGI(TAG, "Display is I2C on port %u", address); - } else if (sys_display->which_dispType == sys_display_config_spi_tag && spi_system_host != -1) { - int CS_pin = -1, speed = 0, mode = 0; - CS_pin = sys_display->dispType.spi.cs; - speed = sys_display->dispType.spi.speed; - mode = sys_display->dispType.spi.mode; - - init = true; - GDS_SPIInit( spi_system_host, spi_system_dc_gpio ); - GDS_SPIAttachDevice( display, width, height, CS_pin, RST_pin, backlight_pin, speed, mode ); - - ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin); - } else { - display = NULL; - ESP_LOGI(TAG, "Unsupported display interface or serial link not configured"); - } - } - - - if (init) { - static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); - static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__ ((aligned (4))); - struct GDS_Layout Layout = { - .HFlip = platform->dev.display.common.HFlip, - .VFlip = platform->dev.display.common.VFlip, - .Rotate = platform->dev.display.common.rotate, - .Invert = platform->dev.display.common.invert, - .ColorSwap = platform->dev.display.common.colow_swap - }; + // Detect driver interface + if(sys_display->which_dispType == sys_display_config_i2c_tag && platform->dev.i2c.port != sys_i2c_port_UNSPECIFIED) { + int address = 0x3C; - GDS_SetLayout(display, &Layout); - GDS_SetFont(display, Font_line_2); - GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome); + address = sys_display->dispType.i2c.address; + init = true; + GDS_I2CInit(platform->dev.i2c.port - sys_i2c_port_PORT0, -1, -1, platform->dev.i2c.speed); + GDS_I2CAttachDevice(display, width, height, address, RST_pin, backlight_pin); + + ESP_LOGI(TAG, "Display is I2C on port %u", address); + } else if(sys_display->which_dispType == sys_display_config_spi_tag && spi_system_host != -1) { + int CS_pin = -1, speed = 0, mode = 0; + CS_pin = sys_display->dispType.spi.cs; + speed = sys_display->dispType.spi.speed; + mode = sys_display->dispType.spi.mode; + + init = true; + GDS_SPIInit(spi_system_host, spi_system_dc_gpio); + GDS_SPIAttachDevice(display, width, height, CS_pin, RST_pin, backlight_pin, speed, mode); + + ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin); + } else { + display = NULL; + ESP_LOGI(TAG, "Unsupported display interface or serial link not configured"); + } + } + + if(init) { + static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__((aligned(4))); + static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__((aligned(4))); + struct GDS_Layout Layout = {.HFlip = platform->dev.display.common.HFlip, + .VFlip = platform->dev.display.common.VFlip, + .Rotate = platform->dev.display.common.rotate, + .Invert = platform->dev.display.common.invert, + .ColorSwap = platform->dev.display.common.colow_swap}; + + GDS_SetLayout(display, &Layout); + GDS_SetFont(display, Font_line_2); + GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome); + + // start the task that will handle scrolling & counting + displayer.mutex = xSemaphoreCreateMutex(); + displayer.by = 2; + displayer.pause = 3600; + displayer.speed = 33; + displayer.task = xTaskCreateStatic( + (TaskFunction_t)displayer_task, "common_displayer", DISPLAYER_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer); + + // set lines for "fixed" text mode + GDS_TextSetFontAuto(display, 1, GDS_FONT_LINE_1, -3); + GDS_TextSetFontAuto(display, 2, GDS_FONT_LINE_2, -3); + + if(platform->has_services && platform->services.has_metadata) { + displayer.metadata_config = &platform->services.metadata; + + // leave room for artwork is display is horizontal-style + if(displayer.metadata_config->has_artwork && displayer.metadata_config->artwork.enabled) { +#pragma message("todo: check for resize flag and possibly offsets?") + displayer.artwork.enable = true; + displayer.artwork.fit = true; + if(height <= 64 && width > height * 2) displayer.artwork.offset = width - height - ARTWORK_BORDER; + } + } - // start the task that will handle scrolling & counting - displayer.mutex = xSemaphoreCreateMutex(); - displayer.by = 2; - displayer.pause = 3600; - displayer.speed = 33; - displayer.task = xTaskCreateStatic( (TaskFunction_t) displayer_task, "common_displayer", DISPLAYER_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer); - - // set lines for "fixed" text mode - GDS_TextSetFontAuto(display, 1, GDS_FONT_LINE_1, -3); - GDS_TextSetFontAuto(display, 2, GDS_FONT_LINE_2, -3); - - if(platform->has_services && platform->services.has_metadata){ - displayer.metadata_config = &platform->services.metadata; - - // leave room for artwork is display is horizontal-style - if (displayer.metadata_config->has_artwork && displayer.metadata_config->artwork.enabled) { - #pragma message("todo: check for resize flag and possibly offsets?") - displayer.artwork.enable = true; - displayer.artwork.fit = true; - if (height <= 64 && width > height * 2) - displayer.artwork.offset = width - height - ARTWORK_BORDER; - } - } - - // and finally register ourselves to power off upon deep sleep services_sleep_setsuspend(display_sleep); - } - - + } } /**************************************************************************************** * */ -static void display_sleep(void) { - GDS_DisplayOff(display); -} +static void display_sleep(void) { GDS_DisplayOff(display); } /**************************************************************************************** * This is not thread-safe as displayer_task might be in the middle of line drawing * but it won't crash (I think) and making it thread-safe would be complicated for a * feature which is secondary (the LMS version of scrolling is thread-safe) */ -static void displayer_task(void *args) { - int scroll_sleep = 0, timer_sleep; - - while (1) { - // suspend ourselves if nothing to do - if (displayer.state < DISPLAYER_ACTIVE) { - if (displayer.state == DISPLAYER_IDLE) GDS_TextLine(display, 2, 0, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, displayer.string); - vTaskSuspend(NULL); - scroll_sleep = 0; - GDS_ClearExt(display, true); - GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_UPDATE, displayer.header); - } else if (displayer.refresh) { - // little trick when switching master while in IDLE and missing it - GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, displayer.header); - displayer.refresh = false; - } - - // we have been waken up before our requested time - if (scroll_sleep <= 10) { - // something to scroll (or we'll wake-up every pause ms ... no big deal) - if (*displayer.string && displayer.state == DISPLAYER_ACTIVE) { - xSemaphoreTake(displayer.mutex, portMAX_DELAY); - - // need to work with local copies as we don't want to suspend caller - int offset = -displayer.offset; - char *string = strdup(displayer.string); - scroll_sleep = displayer.offset ? displayer.speed : displayer.pause; - displayer.offset = displayer.offset >= displayer.boundary ? 0 : (displayer.offset + min(displayer.by, displayer.boundary - displayer.offset)); - - xSemaphoreGive(displayer.mutex); - - // now display using safe copies, can be lengthy - GDS_TextLine(display, 2, offset, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, string); - free(string); - } else { - scroll_sleep = DEFAULT_SLEEP; - } - } - - // handler elapsed track time - if (displayer.timer && displayer.state == DISPLAYER_ACTIVE) { - char line[19] = "-", *_line = line + 1; // [-]H:MM:SS / H:MM:SS - TickType_t tick = xTaskGetTickCount(); - uint32_t elapsed = (tick - displayer.tick) * portTICK_PERIOD_MS; +static void displayer_task(void* args) { + int scroll_sleep = 0, timer_sleep; - if (elapsed >= 1000) { - xSemaphoreTake(displayer.mutex, portMAX_DELAY); - displayer.tick = tick; - elapsed = displayer.elapsed += elapsed / 1000; - xSemaphoreGive(displayer.mutex); + while(1) { + // suspend ourselves if nothing to do + if(displayer.state < DISPLAYER_ACTIVE) { + if(displayer.state == DISPLAYER_IDLE) GDS_TextLine(display, 2, 0, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, displayer.string); + vTaskSuspend(NULL); + scroll_sleep = 0; + GDS_ClearExt(display, true); + GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_UPDATE, displayer.header); + } else if(displayer.refresh) { + // little trick when switching master while in IDLE and missing it + GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, displayer.header); + displayer.refresh = false; + } - // when we have duration but no space, display remaining time - if (displayer.duration.value && !displayer.duration.visible) elapsed = displayer.duration.value - elapsed; + // we have been waken up before our requested time + if(scroll_sleep <= 10) { + // something to scroll (or we'll wake-up every pause ms ... no big deal) + if(*displayer.string && displayer.state == DISPLAYER_ACTIVE) { + xSemaphoreTake(displayer.mutex, portMAX_DELAY); - if (elapsed < 3600) sprintf(_line, "%lu:%02lu", (unsigned long) (elapsed / 60), (unsigned long) (elapsed % 60)); - else sprintf(_line, "%lu:%02lu:%02lu", (unsigned long) ((elapsed / 3600) % 100), - (unsigned long) ((elapsed % 3600) / 60), (unsigned long) (elapsed % 60)); + // need to work with local copies as we don't want to suspend caller + int offset = -displayer.offset; + char* string = strdup(displayer.string); + scroll_sleep = displayer.offset ? displayer.speed : displayer.pause; + displayer.offset = + displayer.offset >= displayer.boundary ? 0 : (displayer.offset + min(displayer.by, displayer.boundary - displayer.offset)); - // concatenate if we have room for elapsed / duration - if (displayer.duration.visible) { - strcat(_line, "/"); - strcat(_line, displayer.duration.string); - } else if (displayer.duration.value) { - _line--; - } + xSemaphoreGive(displayer.mutex); - // just re-write the whole line it's easier - GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header); - GDS_TextLine(display, 1, GDS_TEXT_RIGHT, GDS_TEXT_UPDATE, _line); - - // if we have not received artwork after 5s, display a default icon - if (displayer.artwork.active && !displayer.artwork.updated && tick - displayer.artwork.tick > pdMS_TO_TICKS(5000)) { - ESP_LOGI(TAG, "no artwork received, setting default"); - displayer_artwork((uint8_t*) default_artwork); - } - timer_sleep = 1000; - } else timer_sleep = max(1000 - elapsed, 0); - } else timer_sleep = DEFAULT_SLEEP; - - // then sleep the min amount of time - int sleep = min(scroll_sleep, timer_sleep); - ESP_LOGD(TAG, "timers s:%d t:%d", scroll_sleep, timer_sleep); - scroll_sleep -= sleep; - vTaskDelay(sleep / portTICK_PERIOD_MS); - } -} + // now display using safe copies, can be lengthy + GDS_TextLine(display, 2, offset, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, string); + free(string); + } else { + scroll_sleep = DEFAULT_SLEEP; + } + } -/**************************************************************************************** - * - */ -void displayer_artwork(uint8_t *data) { - if (!displayer.artwork.active) return; - - int x = displayer.artwork.offset ? displayer.artwork.offset + ARTWORK_BORDER : 0; - int y = x ? 0 : 32; - GDS_ClearWindow(display, x, y, -1, -1, GDS_COLOR_BLACK); - if (data) { - displayer.artwork.updated = true; - GDS_DrawJPEG(display, data, x, y, GDS_IMAGE_CENTER | (displayer.artwork.fit ? GDS_IMAGE_FIT : 0)); - } else { - displayer.artwork.updated = false; - displayer.artwork.tick = xTaskGetTickCount(); - } - + // handler elapsed track time + if(displayer.timer && displayer.state == DISPLAYER_ACTIVE) { + char line[19] = "-", *_line = line + 1; // [-]H:MM:SS / H:MM:SS + TickType_t tick = xTaskGetTickCount(); + uint32_t elapsed = (tick - displayer.tick) * portTICK_PERIOD_MS; + + if(elapsed >= 1000) { + xSemaphoreTake(displayer.mutex, portMAX_DELAY); + displayer.tick = tick; + elapsed = displayer.elapsed += elapsed / 1000; + xSemaphoreGive(displayer.mutex); + + // when we have duration but no space, display remaining time + if(displayer.duration.value && !displayer.duration.visible) elapsed = displayer.duration.value - elapsed; + + if(elapsed < 3600) + sprintf(_line, "%lu:%02lu", (unsigned long)(elapsed / 60), (unsigned long)(elapsed % 60)); + else + sprintf(_line, "%lu:%02lu:%02lu", (unsigned long)((elapsed / 3600) % 100), (unsigned long)((elapsed % 3600) / 60), + (unsigned long)(elapsed % 60)); + + // concatenate if we have room for elapsed / duration + if(displayer.duration.visible) { + strcat(_line, "/"); + strcat(_line, displayer.duration.string); + } else if(displayer.duration.value) { + _line--; + } + + // just re-write the whole line it's easier + GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header); + GDS_TextLine(display, 1, GDS_TEXT_RIGHT, GDS_TEXT_UPDATE, _line); + + // if we have not received artwork after 5s, display a default icon + if(displayer.artwork.active && !displayer.artwork.updated && tick - displayer.artwork.tick > pdMS_TO_TICKS(5000)) { + ESP_LOGI(TAG, "no artwork received, setting default"); + displayer_artwork((uint8_t*)default_artwork); + } + timer_sleep = 1000; + } else + timer_sleep = max(1000 - elapsed, 0); + } else + timer_sleep = DEFAULT_SLEEP; + + // then sleep the min amount of time + int sleep = min(scroll_sleep, timer_sleep); + ESP_LOGD(TAG, "timers s:%d t:%d", scroll_sleep, timer_sleep); + scroll_sleep -= sleep; + vTaskDelay(sleep / portTICK_PERIOD_MS); + } } /**************************************************************************************** * */ -bool displayer_can_artwork(void) { - return displayer.artwork.active; +void displayer_artwork(uint8_t* data) { + if(!displayer.artwork.active) return; + + int x = displayer.artwork.offset ? displayer.artwork.offset + ARTWORK_BORDER : 0; + int y = x ? 0 : 32; + GDS_ClearWindow(display, x, y, -1, -1, GDS_COLOR_BLACK); + if(data) { + displayer.artwork.updated = true; + GDS_DrawJPEG(display, data, x, y, GDS_IMAGE_CENTER | (displayer.artwork.fit ? GDS_IMAGE_FIT : 0)); + } else { + displayer.artwork.updated = false; + displayer.artwork.tick = xTaskGetTickCount(); + } } /**************************************************************************************** * */ -void displayer_metadata(char *artist, char *album, char *title) { - char *string = displayer.string, *p; - int len = SCROLLABLE_SIZE; - - // need a display! - if (!display) return; - - // just do title if there is no config set - if (!displayer.metadata_config) { - strncpy(displayer.string, title ? title : "", SCROLLABLE_SIZE); - return; - } - - xSemaphoreTake(displayer.mutex, portMAX_DELAY); - - // format metadata parameters and write them directly - if (strlen(displayer.metadata_config->format)>0) { - char token[16], *q; - int space = len; - bool skip = false; - - displayer.string[0] = '\0'; - p = strchr(displayer.metadata_config->format, '='); - - while (p++) { - // find token and copy what's after when reaching last one - if (sscanf(p, "%*[^%%]%%%[^%]%%", token) < 0) { - q = strchr(p, ','); - strncat(string, p, q ? min(q - p, space) : space); - break; - } +bool displayer_can_artwork(void) { return displayer.artwork.active; } - // copy what's before token (be safe) - if ((q = strchr(p, '%')) == NULL) break; - - // skip whatever is after a token if this token is empty - if (!skip) { - strncat(string, p, min(q - p, space)); - space = len - strlen(string); - } +/**************************************************************************************** + * + */ +void displayer_metadata(char* artist, char* album, char* title) { + char *string = displayer.string, *p; + int len = SCROLLABLE_SIZE; - // then copy token's content - if (!strncasecmp(q + 1, "artist", 6) && artist) strncat(string, p = artist, space); - else if (!strncasecmp(q + 1, "album", 5) && album) strncat(string, p = album, space); - else if (!strncasecmp(q + 1, "title", 5) && title) strncat(string, p = title, space); - space = len - strlen(string); - - // flag to skip the data following an empty field - if (*p) skip = false; - else skip = true; + // need a display! + if(!display) return; - // advance to next separator - p = strchr(q + 1, '%'); - } - } else { - strncpy(string, title ? title : "", SCROLLABLE_SIZE); - } - if(displayer.metadata_config->speed <=0) displayer.metadata_config->speed= displayer.speed; - if(displayer.metadata_config->pause <=0) displayer.metadata_config->pause= displayer.pause; - displayer.metadata_config->speed = displayer.speed; - displayer.offset = 0; - utf8_decode(displayer.string); - ESP_LOGI(TAG, "playing %s", displayer.string); - displayer.boundary = GDS_TextStretch(display, 2, displayer.string, SCROLLABLE_SIZE); - - xSemaphoreGive(displayer.mutex); -} + // just do title if there is no config set + if(!displayer.metadata_config) { + strncpy(displayer.string, title ? title : "", SCROLLABLE_SIZE); + return; + } + + xSemaphoreTake(displayer.mutex, portMAX_DELAY); + + // format metadata parameters and write them directly + if(strlen(displayer.metadata_config->format) > 0) { + char token[16], *q; + int space = len; + bool skip = false; + + displayer.string[0] = '\0'; + p = strchr(displayer.metadata_config->format, '='); + + while(p++) { + // find token and copy what's after when reaching last one + if(sscanf(p, "%*[^%%]%%%[^%]%%", token) < 0) { + q = strchr(p, ','); + strncat(string, p, q ? min(q - p, space) : space); + break; + } + + // copy what's before token (be safe) + if((q = strchr(p, '%')) == NULL) break; + + // skip whatever is after a token if this token is empty + if(!skip) { + strncat(string, p, min(q - p, space)); + space = len - strlen(string); + } + + // then copy token's content + if(!strncasecmp(q + 1, "artist", 6) && artist) + strncat(string, p = artist, space); + else if(!strncasecmp(q + 1, "album", 5) && album) + strncat(string, p = album, space); + else if(!strncasecmp(q + 1, "title", 5) && title) + strncat(string, p = title, space); + space = len - strlen(string); + + // flag to skip the data following an empty field + if(*p) + skip = false; + else + skip = true; + + // advance to next separator + p = strchr(q + 1, '%'); + } + } else { + strncpy(string, title ? title : "", SCROLLABLE_SIZE); + } + if(displayer.metadata_config->speed <= 0) displayer.metadata_config->speed = displayer.speed; + if(displayer.metadata_config->pause <= 0) displayer.metadata_config->pause = displayer.pause; + displayer.metadata_config->speed = displayer.speed; + displayer.offset = 0; + utf8_decode(displayer.string); + ESP_LOGI(TAG, "playing %s", displayer.string); + displayer.boundary = GDS_TextStretch(display, 2, displayer.string, SCROLLABLE_SIZE); + + xSemaphoreGive(displayer.mutex); +} /**************************************************************************************** * */ -void displayer_scroll(char *string, int speed, int pause) { - // need a display! - if (!display) return; - - xSemaphoreTake(displayer.mutex, portMAX_DELAY); +void displayer_scroll(char* string, int speed, int pause) { + // need a display! + if(!display) return; - if (speed) displayer.speed = speed; - if (pause) displayer.pause = pause; - displayer.offset = 0; - strncpy(displayer.string, string, SCROLLABLE_SIZE); - displayer.string[SCROLLABLE_SIZE] = '\0'; - displayer.boundary = GDS_TextStretch(display, 2, displayer.string, SCROLLABLE_SIZE); - - xSemaphoreGive(displayer.mutex); + xSemaphoreTake(displayer.mutex, portMAX_DELAY); + + if(speed) displayer.speed = speed; + if(pause) displayer.pause = pause; + displayer.offset = 0; + strncpy(displayer.string, string, SCROLLABLE_SIZE); + displayer.string[SCROLLABLE_SIZE] = '\0'; + displayer.boundary = GDS_TextStretch(display, 2, displayer.string, SCROLLABLE_SIZE); + + xSemaphoreGive(displayer.mutex); } /**************************************************************************************** * */ void displayer_timer(enum displayer_time_e mode, int elapsed, int duration) { - // need a display! - if (!display) return; - - xSemaphoreTake(displayer.mutex, portMAX_DELAY); + // need a display! + if(!display) return; - if (displayer.timer) displayer.tick = xTaskGetTickCount(); - if (elapsed >= 0) displayer.elapsed = elapsed / 1000; - if (duration > 0) { - displayer.duration.visible = true; - displayer.duration.value = duration / 1000; + xSemaphoreTake(displayer.mutex, portMAX_DELAY); - if (displayer.duration.value > 3600) sprintf(displayer.duration.string, "%lu:%02lu:%02lu", - (unsigned long) ((displayer.duration.value / 3600) % 10), - (unsigned long) ((displayer.duration.value % 3600) / 60), - (unsigned long) (displayer.duration.value % 60)); - else sprintf(displayer.duration.string, "%lu:%02lu", (unsigned long) (displayer.duration.value / 60), - (unsigned long) (displayer.duration.value % 60)); + if(displayer.timer) displayer.tick = xTaskGetTickCount(); + if(elapsed >= 0) displayer.elapsed = elapsed / 1000; + if(duration > 0) { + displayer.duration.visible = true; + displayer.duration.value = duration / 1000; - char *buf; - asprintf(&buf, "%s %s/%s", displayer.header, displayer.duration.string, displayer.duration.string); - if (GDS_GetTextWidth(display, 1, 0, buf) > GDS_GetWidth(display)) { - ESP_LOGW(TAG, "Can't fit duration %s (%d) on screen using elapsed only", buf, GDS_GetTextWidth(display, 1, 0, buf)); - displayer.duration.visible = false; - } - free(buf); - } else if (!duration) { - displayer.duration.visible = false; - displayer.duration.value = 0; - } - - xSemaphoreGive(displayer.mutex); -} + if(displayer.duration.value > 3600) + sprintf(displayer.duration.string, "%lu:%02lu:%02lu", (unsigned long)((displayer.duration.value / 3600) % 10), + (unsigned long)((displayer.duration.value % 3600) / 60), (unsigned long)(displayer.duration.value % 60)); + else + sprintf(displayer.duration.string, "%lu:%02lu", (unsigned long)(displayer.duration.value / 60), + (unsigned long)(displayer.duration.value % 60)); + + char* buf; + asprintf(&buf, "%s %s/%s", displayer.header, displayer.duration.string, displayer.duration.string); + if(GDS_GetTextWidth(display, 1, 0, buf) > GDS_GetWidth(display)) { + ESP_LOGW(TAG, "Can't fit duration %s (%d) on screen using elapsed only", buf, GDS_GetTextWidth(display, 1, 0, buf)); + displayer.duration.visible = false; + } + free(buf); + } else if(!duration) { + displayer.duration.visible = false; + displayer.duration.value = 0; + } + + xSemaphoreGive(displayer.mutex); +} /**************************************************************************************** * See above comment */ void displayer_control(enum displayer_cmd_e cmd, ...) { - va_list args; - - if (!display) return; - - va_start(args, cmd); - xSemaphoreTake(displayer.mutex, portMAX_DELAY); - - switch(cmd) { - case DISPLAYER_ACTIVATE: { - char *header = va_arg(args, char*); - displayer.artwork.active = displayer.artwork.enable && va_arg(args, int); - strncpy(displayer.header, header, HEADER_SIZE); - displayer.header[HEADER_SIZE] = '\0'; - displayer.state = DISPLAYER_ACTIVE; - displayer.timer = false; - displayer.refresh = true; - displayer.string[0] = '\0'; - displayer.elapsed = displayer.duration.value = 0; - displayer.duration.visible = false; - displayer.offset = displayer.boundary = 0; - display_bus(&displayer, DISPLAY_BUS_TAKE); - if (displayer.artwork.active) GDS_SetTextWidth(display, displayer.artwork.offset); - vTaskResume(displayer.task); - break; - } - case DISPLAYER_SUSPEND: - // task will display the line 2 from beginning and suspend - displayer.state = DISPLAYER_IDLE; - displayer_artwork(NULL); - display_bus(&displayer, DISPLAY_BUS_GIVE); - break; - case DISPLAYER_SHUTDOWN: - // let the task self-suspend (we might be doing i2c_write) - GDS_SetTextWidth(display, 0); - displayer_artwork(NULL); - displayer.state = DISPLAYER_DOWN; - display_bus(&displayer, DISPLAY_BUS_GIVE); - break; - case DISPLAYER_TIMER_RUN: - if (!displayer.timer) { - display_bus(&displayer, DISPLAY_BUS_TAKE); - displayer.timer = true; - displayer.tick = xTaskGetTickCount(); - } - break; - case DISPLAYER_TIMER_PAUSE: - displayer.timer = false; - break; - default: - break; - } - - xSemaphoreGive(displayer.mutex); - va_end(args); + va_list args; + + if(!display) return; + + va_start(args, cmd); + xSemaphoreTake(displayer.mutex, portMAX_DELAY); + + switch(cmd) { + case DISPLAYER_ACTIVATE: { + char* header = va_arg(args, char*); + displayer.artwork.active = displayer.artwork.enable && va_arg(args, int); + strncpy(displayer.header, header, HEADER_SIZE); + displayer.header[HEADER_SIZE] = '\0'; + displayer.state = DISPLAYER_ACTIVE; + displayer.timer = false; + displayer.refresh = true; + displayer.string[0] = '\0'; + displayer.elapsed = displayer.duration.value = 0; + displayer.duration.visible = false; + displayer.offset = displayer.boundary = 0; + display_bus(&displayer, DISPLAY_BUS_TAKE); + if(displayer.artwork.active) GDS_SetTextWidth(display, displayer.artwork.offset); + vTaskResume(displayer.task); + break; + } + case DISPLAYER_SUSPEND: + // task will display the line 2 from beginning and suspend + displayer.state = DISPLAYER_IDLE; + displayer_artwork(NULL); + display_bus(&displayer, DISPLAY_BUS_GIVE); + break; + case DISPLAYER_SHUTDOWN: + // let the task self-suspend (we might be doing i2c_write) + GDS_SetTextWidth(display, 0); + displayer_artwork(NULL); + displayer.state = DISPLAYER_DOWN; + display_bus(&displayer, DISPLAY_BUS_GIVE); + break; + case DISPLAYER_TIMER_RUN: + if(!displayer.timer) { + display_bus(&displayer, DISPLAY_BUS_TAKE); + displayer.timer = true; + displayer.tick = xTaskGetTickCount(); + } + break; + case DISPLAYER_TIMER_PAUSE: + displayer.timer = false; + break; + default: + break; + } + + xSemaphoreGive(displayer.mutex); + va_end(args); } diff --git a/components/display/display.h b/components/display/display.h index f82afa4d..13d94967 100644 --- a/components/display/display.h +++ b/components/display/display.h @@ -10,7 +10,6 @@ #include "gds.h" - /* The displayer is not thread-safe and the caller must ensure use its own mutexes if it wants something better. Especially, text() line() and draw() @@ -24,18 +23,18 @@ The display_bus() shall be subscribed by other displayers so that at least when this one (the main) wants to take control over display, it can signal that to others -*/ -extern struct GDS_Device *display; - -enum displayer_cmd_e { DISPLAYER_SHUTDOWN, DISPLAYER_ACTIVATE, DISPLAYER_SUSPEND, DISPLAYER_TIMER_PAUSE, DISPLAYER_TIMER_RUN }; -enum displayer_time_e { DISPLAYER_ELAPSED, DISPLAYER_REMAINING }; +*/ +extern struct GDS_Device* display; + +enum displayer_cmd_e { DISPLAYER_SHUTDOWN, DISPLAYER_ACTIVATE, DISPLAYER_SUSPEND, DISPLAYER_TIMER_PAUSE, DISPLAYER_TIMER_RUN }; +enum displayer_time_e { DISPLAYER_ELAPSED, DISPLAYER_REMAINING }; enum display_bus_cmd_e { DISPLAY_BUS_TAKE, DISPLAY_BUS_GIVE }; -extern bool (*display_bus)(void *from, enum display_bus_cmd_e cmd); +extern bool (*display_bus)(void* from, enum display_bus_cmd_e cmd); -void displayer_scroll(char *string, int speed, int pause); +void displayer_scroll(char* string, int speed, int pause); void displayer_control(enum displayer_cmd_e cmd, ...); -void displayer_metadata(char *artist, char *album, char *title); -void displayer_artwork(uint8_t *data); +void displayer_metadata(char* artist, char* album, char* title); +void displayer_artwork(uint8_t* data); void displayer_timer(enum displayer_time_e mode, int elapsed, int duration); bool displayer_can_artwork(void); diff --git a/components/driver_bt/bt_app_core.c b/components/driver_bt/bt_app_core.c index 48f595cb..590da798 100644 --- a/components/driver_bt/bt_app_core.c +++ b/components/driver_bt/bt_app_core.c @@ -28,8 +28,7 @@ static void bt_app_work_dispatched(bt_app_msg_t* msg); static QueueHandle_t s_bt_app_task_queue; static bool running; -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, int param_len, - bt_app_copy_cb_t p_copy_cback) { +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, int param_len, bt_app_copy_cb_t p_copy_cback) { ESP_LOGV(TAG, "%s event 0x%x, param len %d", __func__, event, param_len); bt_app_msg_t msg; @@ -39,14 +38,12 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, i msg.event = event; msg.cb = p_cback; - if (param_len == 0) { + if(param_len == 0) { return bt_app_send_msg(&msg); - } else if (p_params && param_len > 0) { - if ((msg.param = clone_obj_psram(p_params, param_len)) != NULL) { + } else if(p_params && param_len > 0) { + if((msg.param = clone_obj_psram(p_params, param_len)) != NULL) { /* check if caller has provided a copy callback to do the deep copy */ - if (p_copy_cback) { - p_copy_cback(&msg, msg.param, p_params); - } + if(p_copy_cback) { p_copy_cback(&msg, msg.param, p_params); } return bt_app_send_msg(&msg); } } @@ -55,11 +52,9 @@ bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, i } static bool bt_app_send_msg(bt_app_msg_t* msg) { - if (msg == NULL) { - return false; - } + if(msg == NULL) { return false; } - if (xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) { + if(xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) { ESP_LOGE(TAG, "%s xQueue send failed", __func__); return false; } @@ -67,9 +62,7 @@ static bool bt_app_send_msg(bt_app_msg_t* msg) { } static void bt_app_work_dispatched(bt_app_msg_t* msg) { - if (msg->cb) { - msg->cb(msg->event, msg->param); - } + if(msg->cb) { msg->cb(msg->event, msg->param); } } static void bt_app_task_handler(void* arg) { @@ -80,23 +73,23 @@ static void bt_app_task_handler(void* arg) { esp_bt_controller_mem_release(ESP_BT_MODE_BLE); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) { - if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) { + if((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err)); goto exit; } - if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { + if((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(err)); goto exit; } - if ((err = esp_bluedroid_init()) != ESP_OK) { + if((err = esp_bluedroid_init()) != ESP_OK) { ESP_LOGE(TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(err)); goto exit; } - if ((err = esp_bluedroid_enable()) != ESP_OK) { + if((err = esp_bluedroid_enable()) != ESP_OK) { ESP_LOGE(TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(err)); goto exit; } @@ -104,7 +97,7 @@ static void bt_app_task_handler(void* arg) { /* Bluetooth device name, connection mode and profile set up */ bt_app_work_dispatch((bt_av_hdl_stack_evt_t*)arg, BT_APP_EVT_STACK_UP, NULL, 0, NULL); -#if (CONFIG_BT_SSP_ENABLED) +#if(CONFIG_BT_SSP_ENABLED) /* Set default parameters for Secure Simple Pairing */ esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; @@ -121,11 +114,11 @@ static void bt_app_task_handler(void* arg) { running = true; - while (running) { - if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, portMAX_DELAY)) { + while(running) { + if(pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, portMAX_DELAY)) { ESP_LOGV(TAG, "%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); - switch (msg.sig) { + switch(msg.sig) { case BT_APP_SIG_WORK_DISPATCH: bt_app_work_dispatched(&msg); break; @@ -134,9 +127,7 @@ static void bt_app_task_handler(void* arg) { break; } - if (msg.param) { - free(msg.param); - } + if(msg.param) { free(msg.param); } } else { ESP_LOGW(TAG, "No messaged received from queue."); } @@ -144,19 +135,19 @@ static void bt_app_task_handler(void* arg) { ESP_LOGD(TAG, "bt_app_task shutting down"); - if (esp_bluedroid_disable() != ESP_OK) goto exit; + if(esp_bluedroid_disable() != ESP_OK) goto exit; // this disable has a sleep timer BTA_DISABLE_DELAY in bt_target.h and // if we don't wait for it then disable crashes... don't know why vTaskDelay(2 * 200 / portTICK_PERIOD_MS); ESP_LOGD(TAG, "esp_bluedroid_disable called successfully"); - if (esp_bluedroid_deinit() != ESP_OK) goto exit; + if(esp_bluedroid_deinit() != ESP_OK) goto exit; ESP_LOGD(TAG, "esp_bluedroid_deinit called successfully"); - if (esp_bt_controller_disable() != ESP_OK) goto exit; + if(esp_bt_controller_disable() != ESP_OK) goto exit; ESP_LOGD(TAG, "esp_bt_controller_disable called successfully"); - if (esp_bt_controller_deinit() != ESP_OK) goto exit; + if(esp_bt_controller_deinit() != ESP_OK) goto exit; ESP_LOGD(TAG, "bt stopped successfully"); diff --git a/components/driver_bt/bt_app_core.h b/components/driver_bt/bt_app_core.h index 7ef70c90..8d377e4a 100644 --- a/components/driver_bt/bt_app_core.h +++ b/components/driver_bt/bt_app_core.h @@ -52,8 +52,7 @@ typedef void bt_av_hdl_stack_evt_t(uint16_t event, void* p_param); /** * @brief work dispatcher for the application task */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, int param_len, - bt_app_copy_cb_t p_copy_cback); +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void* p_params, int param_len, bt_app_copy_cb_t p_copy_cback); void bt_app_task_start_up(bt_av_hdl_stack_evt_t* handler); diff --git a/components/driver_bt/bt_app_sink.c b/components/driver_bt/bt_app_sink.c index 16fa5ccf..13a19bea 100644 --- a/components/driver_bt/bt_app_sink.c +++ b/components/driver_bt/bt_app_sink.c @@ -31,37 +31,36 @@ #include "accessors.h" // AVRCP used transaction label -#define APP_RC_CT_TL_GET_CAPS (0) -#define APP_RC_CT_TL_GET_META_DATA (1) -#define APP_RC_CT_TL_RN_TRACK_CHANGE (2) -#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3) -#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4) +#define APP_RC_CT_TL_GET_CAPS (0) +#define APP_RC_CT_TL_GET_META_DATA (1) +#define APP_RC_CT_TL_RN_TRACK_CHANGE (2) +#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3) +#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4) static const char BT_AV_TAG[] = "BT_AV"; static const char BT_RC_TG_TAG[] = "RCTG"; static const char BT_RC_CT_TAG[] = "RCCT"; #ifndef CONFIG_BT_NAME -#define CONFIG_BT_NAME "ESP32-BT" +#define CONFIG_BT_NAME "ESP32-BT" #endif - static bool (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...); -static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len); +static void (*bt_app_a2d_data_cb)(const uint8_t* data, uint32_t len); /* handler for bluetooth stack enabled events */ -static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); +static void bt_av_hdl_stack_evt(uint16_t event, void* p_param); /* a2dp event handler */ -static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param); +static void bt_av_hdl_a2d_evt(uint16_t event, void* p_param); /* avrc CT event handler */ -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param); +static void bt_av_hdl_avrc_ct_evt(uint16_t event, void* p_param); /* avrc TG event handler */ -static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param); +static void bt_av_hdl_avrc_tg_evt(uint16_t event, void* p_param); static void volume_set_by_local_host(int value, bool is_step); -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter); +static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t* event_parameter); -static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; -static const char *s_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"}; +static const char* s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; +static const char* s_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"}; static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; static _lock_t s_volume_lock; @@ -76,137 +75,139 @@ static bt_cmd_vcb_t cmd_handler_chain; #define METADATA_LEN 128 static EXT_RAM_ATTR struct { - char artist[METADATA_LEN + 1]; - char album[METADATA_LEN + 1]; - char title[METADATA_LEN + 1]; - int duration; - bool updated; -} s_metadata; + char artist[METADATA_LEN + 1]; + char album[METADATA_LEN + 1]; + char title[METADATA_LEN + 1]; + int duration; + bool updated; +} s_metadata; static void bt_volume_up(bool pressed) { - if (!pressed) return; - volume_set_by_local_host(+3, true); - (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); - ESP_LOGD(BT_AV_TAG, "BT volume up %u", s_volume); + if(!pressed) return; + volume_set_by_local_host(+3, true); + (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); + ESP_LOGD(BT_AV_TAG, "BT volume up %u", s_volume); } static void bt_volume_down(bool pressed) { - if (!pressed) return; - volume_set_by_local_host(-3, true); - (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); + if(!pressed) return; + volume_set_by_local_host(-3, true); + (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); } static void bt_toggle(bool pressed) { - if (!pressed) return; - if (s_audio == AUDIO_PLAYING) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); - else esp_avrc_ct_send_passthrough_cmd(tl++, ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STATE_PRESSED); + if(!pressed) return; + if(s_audio == AUDIO_PLAYING) + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + else + esp_avrc_ct_send_passthrough_cmd(tl++, ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STATE_PRESSED); } static void bt_play(bool pressed) { - if (!pressed) return; - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STATE_PRESSED); + if(!pressed) return; + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STATE_PRESSED); } static void bt_pause(bool pressed) { - if (!pressed) return; - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_PAUSE, ESP_AVRC_PT_CMD_STATE_PRESSED); + if(!pressed) return; + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_PAUSE, ESP_AVRC_PT_CMD_STATE_PRESSED); } static void bt_stop(bool pressed) { - if (!pressed) return; - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + if(!pressed) return; + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); } static void bt_prev(bool pressed) { - if (!pressed) return; - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_BACKWARD, ESP_AVRC_PT_CMD_STATE_PRESSED); + if(!pressed) return; + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_BACKWARD, ESP_AVRC_PT_CMD_STATE_PRESSED); } static void bt_next(bool pressed) { - if (!pressed) return; - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_FORWARD, ESP_AVRC_PT_CMD_STATE_PRESSED); + if(!pressed) return; + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_FORWARD, ESP_AVRC_PT_CMD_STATE_PRESSED); } const static actrls_t controls = { - NULL, // power - bt_volume_up, bt_volume_down, // volume up, volume down - bt_toggle, bt_play, // toggle, play - bt_pause, bt_stop, // pause, stop - NULL, NULL, // rew, fwd - bt_prev, bt_next, // prev, next - NULL, NULL, NULL, NULL, // left, right, up, down - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 - bt_volume_down, bt_volume_up, bt_toggle// knob left, knob_right, knob push + NULL, // power + bt_volume_up, bt_volume_down, // volume up, volume down + bt_toggle, bt_play, // toggle, play + bt_pause, bt_stop, // pause, stop + NULL, NULL, // rew, fwd + bt_prev, bt_next, // prev, next + NULL, NULL, NULL, NULL, // left, right, up, down + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 + bt_volume_down, bt_volume_up, bt_toggle // knob left, knob_right, knob push }; /* disconnection */ void bt_disconnect(void) { - displayer_control(DISPLAYER_SHUTDOWN); - if (s_audio == AUDIO_PLAYING) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); - actrls_unset(); - ESP_LOGD(BT_AV_TAG, "forced disconnection %d", s_audio); + displayer_control(DISPLAYER_SHUTDOWN); + if(s_audio == AUDIO_PLAYING) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + actrls_unset(); + ESP_LOGD(BT_AV_TAG, "forced disconnection %d", s_audio); } /* update metadata if any */ void update_metadata(bool force) { - if ((s_metadata.updated || force) && s_audio == AUDIO_PLAYING) { - (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, -1, s_metadata.duration); - (*bt_app_a2d_cmd_cb)(BT_SINK_METADATA, s_metadata.artist, s_metadata.album, s_metadata.title); - s_metadata.updated = false; - } else s_metadata.updated = force; -} + if((s_metadata.updated || force) && s_audio == AUDIO_PLAYING) { + (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, -1, s_metadata.duration); + (*bt_app_a2d_cmd_cb)(BT_SINK_METADATA, s_metadata.artist, s_metadata.album, s_metadata.title); + s_metadata.updated = false; + } else + s_metadata.updated = force; +} /* command handler */ static bool cmd_handler(bt_sink_cmd_t cmd, ...) { - va_list args; - - va_start(args, cmd); - - // handle audio event and stop if forbidden - if (!cmd_handler_chain(cmd, args)) { - va_end(args); - return false; - } - - // now handle events for display - switch(cmd) { - case BT_SINK_AUDIO_STARTED: - displayer_control(DISPLAYER_ACTIVATE, "BLUETOOTH", false); - break; - case BT_SINK_AUDIO_STOPPED: - displayer_control(DISPLAYER_SUSPEND); - break; - case BT_SINK_PLAY: - displayer_control(DISPLAYER_TIMER_RUN); - break; - case BT_SINK_STOP: - // not sure of difference between pause and stop for displayer - case BT_SINK_PAUSE: - displayer_control(DISPLAYER_TIMER_PAUSE); - break; - case BT_SINK_METADATA: { - char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); - displayer_metadata(artist, album, title); - break; - } - case BT_SINK_PROGRESS: { - int elapsed = va_arg(args, int), duration = va_arg(args, int); - displayer_timer(DISPLAYER_ELAPSED, elapsed, duration); - break; - } - default: - break; - } - - va_end(args); - - return true; + va_list args; + + va_start(args, cmd); + + // handle audio event and stop if forbidden + if(!cmd_handler_chain(cmd, args)) { + va_end(args); + return false; + } + + // now handle events for display + switch(cmd) { + case BT_SINK_AUDIO_STARTED: + displayer_control(DISPLAYER_ACTIVATE, "BLUETOOTH", false); + break; + case BT_SINK_AUDIO_STOPPED: + displayer_control(DISPLAYER_SUSPEND); + break; + case BT_SINK_PLAY: + displayer_control(DISPLAYER_TIMER_RUN); + break; + case BT_SINK_STOP: + // not sure of difference between pause and stop for displayer + case BT_SINK_PAUSE: + displayer_control(DISPLAYER_TIMER_PAUSE); + break; + case BT_SINK_METADATA: { + char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); + displayer_metadata(artist, album, title); + break; + } + case BT_SINK_PROGRESS: { + int elapsed = va_arg(args, int), duration = va_arg(args, int); + displayer_timer(DISPLAYER_ELAPSED, elapsed, duration); + break; + } + default: + break; + } + + va_end(args); + + return true; } /* callback for A2DP sink */ -void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) -{ - switch (event) { +void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t* param) { + switch(event) { case ESP_A2D_CONNECTION_STATE_EVT: case ESP_A2D_AUDIO_STATE_EVT: case ESP_A2D_AUDIO_CFG_EVT: { @@ -216,26 +217,24 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_PROF_STATE_EVT: { ESP_LOGI(BT_AV_TAG, "Bluetooth Init complete"); break; - } + } default: ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); break; } } -void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param) -{ - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); - uint8_t *attr_text = (uint8_t *) malloc (rc->meta_rsp.attr_length + 1); +void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t* param) { + esp_avrc_ct_cb_param_t* rc = (esp_avrc_ct_cb_param_t*)(param); + uint8_t* attr_text = (uint8_t*)malloc(rc->meta_rsp.attr_length + 1); memcpy(attr_text, rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); attr_text[rc->meta_rsp.attr_length] = 0; rc->meta_rsp.attr_text = attr_text; } -void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) -{ - switch (event) { +void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t* param) { + switch(event) { case ESP_AVRC_CT_METADATA_RSP_EVT: bt_app_alloc_meta_buffer(param); /* fall through */ @@ -253,9 +252,8 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param } } -void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) -{ - switch (event) { +void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t* param) { + switch(event) { case ESP_AVRC_TG_CONNECTION_STATE_EVT: case ESP_AVRC_TG_REMOTE_FEATURES_EVT: case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: @@ -269,81 +267,76 @@ void bt_app_rc_tg_cb(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param } } -static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) -{ +static void bt_av_hdl_a2d_evt(uint16_t event, void* p_param) { ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event); - esp_a2d_cb_param_t *a2d = NULL; - switch (event) { + esp_a2d_cb_param_t* a2d = NULL; + switch(event) { case ESP_A2D_CONNECTION_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); - uint8_t *bda = a2d->conn_stat.remote_bda; - ESP_LOGD(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", - s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); - if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { + a2d = (esp_a2d_cb_param_t*)(p_param); + uint8_t* bda = a2d->conn_stat.remote_bda; + ESP_LOGD(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], + bda[2], bda[3], bda[4], bda[5]); + if(a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - (*bt_app_a2d_cmd_cb)(BT_SINK_DISCONNECTED); - } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){ - abs_volume = -1; - s_volume = sink_volume; + (*bt_app_a2d_cmd_cb)(BT_SINK_DISCONNECTED); + } else if(a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) { + abs_volume = -1; + s_volume = sink_volume; esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); - (*bt_app_a2d_cmd_cb)(BT_SINK_CONNECTED); + (*bt_app_a2d_cmd_cb)(BT_SINK_CONNECTED); } break; } case ESP_A2D_AUDIO_STATE_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); + a2d = (esp_a2d_cb_param_t*)(p_param); ESP_LOGD(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]); - if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { - s_audio = AUDIO_CONNECTED; + if(ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { + s_audio = AUDIO_CONNECTED; - // send memorized volume for devices that can't do absolute volume - (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); - - // verify that we can take control - if ((*bt_app_a2d_cmd_cb)(BT_SINK_AUDIO_STARTED, s_sample_rate)) { - - // if PLAY is sent before AUDIO_STARTED, generate the event here - s_audio = AUDIO_PLAYING; - (*bt_app_a2d_cmd_cb)(BT_SINK_PLAY); - - // force metadata update - update_metadata(true); - - actrls_set(controls, false, NULL, actrls_ir_action); - } else { - // if decoder is busy, stop it (would be better to not ACK this command, but don't know how) - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); - } - } else if (ESP_A2D_AUDIO_STATE_STOPPED == a2d->audio_stat.state || - ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND == a2d->audio_stat.state) { - (*bt_app_a2d_cmd_cb)(BT_SINK_AUDIO_STOPPED); - s_audio = AUDIO_IDLE; - actrls_unset(); - } + // send memorized volume for devices that can't do absolute volume + (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); + + // verify that we can take control + if((*bt_app_a2d_cmd_cb)(BT_SINK_AUDIO_STARTED, s_sample_rate)) { + + // if PLAY is sent before AUDIO_STARTED, generate the event here + s_audio = AUDIO_PLAYING; + (*bt_app_a2d_cmd_cb)(BT_SINK_PLAY); + + // force metadata update + update_metadata(true); + + actrls_set(controls, false, NULL, actrls_ir_action); + } else { + // if decoder is busy, stop it (would be better to not ACK this command, but don't know how) + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + } + } else if(ESP_A2D_AUDIO_STATE_STOPPED == a2d->audio_stat.state || ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND == a2d->audio_stat.state) { + (*bt_app_a2d_cmd_cb)(BT_SINK_AUDIO_STOPPED); + s_audio = AUDIO_IDLE; + actrls_unset(); + } break; } case ESP_A2D_AUDIO_CFG_EVT: { - a2d = (esp_a2d_cb_param_t *)(p_param); + a2d = (esp_a2d_cb_param_t*)(p_param); ESP_LOGD(BT_AV_TAG, "A2DP audio stream configuration, codec type %d", a2d->audio_cfg.mcc.type); // for now only SBC stream is supported - if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) { + if(a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) { s_sample_rate = 16000; char oct0 = a2d->audio_cfg.mcc.cie.sbc[0]; - if (oct0 & (0x01 << 6)) { + if(oct0 & (0x01 << 6)) { s_sample_rate = 32000; - } else if (oct0 & (0x01 << 5)) { + } else if(oct0 & (0x01 << 5)) { s_sample_rate = 44100; - } else if (oct0 & (0x01 << 4)) { + } else if(oct0 & (0x01 << 4)) { s_sample_rate = 48000; } - (*bt_app_a2d_cmd_cb)(BT_SINK_RATE, s_sample_rate); - - ESP_LOGI(BT_AV_TAG, "Configure audio player %x-%x-%x-%x", - a2d->audio_cfg.mcc.cie.sbc[0], - a2d->audio_cfg.mcc.cie.sbc[1], - a2d->audio_cfg.mcc.cie.sbc[2], - a2d->audio_cfg.mcc.cie.sbc[3]); + (*bt_app_a2d_cmd_cb)(BT_SINK_RATE, s_sample_rate); + + ESP_LOGI(BT_AV_TAG, "Configure audio player %x-%x-%x-%x", a2d->audio_cfg.mcc.cie.sbc[0], a2d->audio_cfg.mcc.cie.sbc[1], + a2d->audio_cfg.mcc.cie.sbc[2], a2d->audio_cfg.mcc.cie.sbc[3]); ESP_LOGI(BT_AV_TAG, "Audio player configured, sample rate=%d", s_sample_rate); } break; @@ -354,94 +347,86 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) } } -static void bt_av_new_track(void) -{ +static void bt_av_new_track(void) { // request metadata uint8_t attr_mask = ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_ARTIST | ESP_AVRC_MD_ATTR_ALBUM | ESP_AVRC_MD_ATTR_PLAYING_TIME; esp_avrc_ct_send_metadata_cmd(APP_RC_CT_TL_GET_META_DATA, attr_mask); // register notification if peer support the event_id - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_TRACK_CHANGE)) { + if(esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, ESP_AVRC_RN_TRACK_CHANGE)) { esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_TRACK_CHANGE, ESP_AVRC_RN_TRACK_CHANGE, 0); } } -static void bt_av_playback_changed(void) -{ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_PLAY_STATUS_CHANGE)) { +static void bt_av_playback_changed(void) { + if(esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, ESP_AVRC_RN_PLAY_STATUS_CHANGE)) { esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_PLAYBACK_CHANGE, ESP_AVRC_RN_PLAY_STATUS_CHANGE, 0); } } -static void bt_av_play_pos_changed(void) -{ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_PLAY_POS_CHANGED)) { +static void bt_av_play_pos_changed(void) { + if(esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, ESP_AVRC_RN_PLAY_POS_CHANGED)) { esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_PLAY_POS_CHANGE, ESP_AVRC_RN_PLAY_POS_CHANGED, 10); } } -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter) -{ - switch (event_id) { +static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t* event_parameter) { + switch(event_id) { case ESP_AVRC_RN_TRACK_CHANGE: - ESP_LOGD(BT_AV_TAG, "Track changed"); + ESP_LOGD(BT_AV_TAG, "Track changed"); bt_av_new_track(); - (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, 0, 0); + (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, 0, 0); break; case ESP_AVRC_RN_PLAY_STATUS_CHANGE: ESP_LOGD(BT_AV_TAG, "Playback status changed: 0x%x", event_parameter->playback); - if (s_audio != AUDIO_IDLE) { - switch (event_parameter->playback) { - case ESP_AVRC_PLAYBACK_PLAYING: - // if decoder is busy then stop (would be better to not ACK this command, but don't know how) - if (s_audio != AUDIO_PLAYING && !(*bt_app_a2d_cmd_cb)(BT_SINK_PLAY)) { - ESP_LOGW(BT_AV_TAG, "Player busy with another controller"); - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); - } else { - s_audio = AUDIO_PLAYING; - update_metadata(false); - } - break; - case ESP_AVRC_PLAYBACK_PAUSED: - s_audio = AUDIO_CONNECTED; - (*bt_app_a2d_cmd_cb)(BT_SINK_PAUSE); - break; - case ESP_AVRC_PLAYBACK_STOPPED: - s_audio = AUDIO_CONNECTED; - (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, 0, -1); - (*bt_app_a2d_cmd_cb)(BT_SINK_STOP); - break; - default: - ESP_LOGW(BT_AV_TAG, "Un-handled event"); - break; - } - } else { - ESP_LOGW(BT_AV_TAG, "Not yet in BT connected mode: 0x%x", event_parameter->playback); - } + if(s_audio != AUDIO_IDLE) { + switch(event_parameter->playback) { + case ESP_AVRC_PLAYBACK_PLAYING: + // if decoder is busy then stop (would be better to not ACK this command, but don't know how) + if(s_audio != AUDIO_PLAYING && !(*bt_app_a2d_cmd_cb)(BT_SINK_PLAY)) { + ESP_LOGW(BT_AV_TAG, "Player busy with another controller"); + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + } else { + s_audio = AUDIO_PLAYING; + update_metadata(false); + } + break; + case ESP_AVRC_PLAYBACK_PAUSED: + s_audio = AUDIO_CONNECTED; + (*bt_app_a2d_cmd_cb)(BT_SINK_PAUSE); + break; + case ESP_AVRC_PLAYBACK_STOPPED: + s_audio = AUDIO_CONNECTED; + (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, 0, -1); + (*bt_app_a2d_cmd_cb)(BT_SINK_STOP); + break; + default: + ESP_LOGW(BT_AV_TAG, "Un-handled event"); + break; + } + } else { + ESP_LOGW(BT_AV_TAG, "Not yet in BT connected mode: 0x%x", event_parameter->playback); + } bt_av_playback_changed(); break; case ESP_AVRC_RN_PLAY_POS_CHANGED: ESP_LOGD(BT_AV_TAG, "Play position changed: %d (ms)", event_parameter->play_pos); - (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, event_parameter->play_pos, -1); + (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, event_parameter->play_pos, -1); bt_av_play_pos_changed(); break; } } -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) -{ +static void bt_av_hdl_avrc_ct_evt(uint16_t event, void* p_param) { ESP_LOGD(BT_RC_CT_TAG, "%s evt %d", __func__, event); - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param); - switch (event) { + esp_avrc_ct_cb_param_t* rc = (esp_avrc_ct_cb_param_t*)(p_param); + switch(event) { case ESP_AVRC_CT_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGD(BT_RC_CT_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + uint8_t* bda = rc->conn_stat.remote_bda; + ESP_LOGD(BT_RC_CT_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", rc->conn_stat.connected, bda[0], bda[1], bda[2], + bda[3], bda[4], bda[5]); - if (rc->conn_stat.connected) { + if(rc->conn_stat.connected) { // get remote supported event_ids of peer AVRCP Target esp_avrc_ct_send_get_rn_capabilities_cmd(APP_RC_CT_TL_GET_CAPS); } else { @@ -456,13 +441,17 @@ static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) } case ESP_AVRC_CT_METADATA_RSP_EVT: { ESP_LOGD(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); - - if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_PLAYING_TIME) s_metadata.duration = atoi((char*) rc->meta_rsp.attr_text); - else if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_TITLE) strncpy(s_metadata.title, (char*) rc->meta_rsp.attr_text, METADATA_LEN); - else if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_ARTIST) strncpy(s_metadata.artist, (char*) rc->meta_rsp.attr_text, METADATA_LEN); - else if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_ALBUM) strncpy(s_metadata.album, (char*) rc->meta_rsp.attr_text, METADATA_LEN); - update_metadata(true); - + + if(rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_PLAYING_TIME) + s_metadata.duration = atoi((char*)rc->meta_rsp.attr_text); + else if(rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_TITLE) + strncpy(s_metadata.title, (char*)rc->meta_rsp.attr_text, METADATA_LEN); + else if(rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_ARTIST) + strncpy(s_metadata.artist, (char*)rc->meta_rsp.attr_text, METADATA_LEN); + else if(rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_ALBUM) + strncpy(s_metadata.album, (char*)rc->meta_rsp.attr_text, METADATA_LEN); + update_metadata(true); + free(rc->meta_rsp.attr_text); break; } @@ -476,8 +465,7 @@ static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) break; } case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { - ESP_LOGD(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, - rc->get_rn_caps_rsp.evt_set.bits); + ESP_LOGD(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, rc->get_rn_caps_rsp.evt_set.bits); s_avrc_peer_rn_cap.bits = rc->get_rn_caps_rsp.evt_set.bits; bt_av_new_track(); bt_av_playback_changed(); @@ -490,30 +478,32 @@ static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) } } -static void volume_set_by_controller(uint8_t volume) -{ - // do not modified state volume +static void volume_set_by_controller(uint8_t volume) { + // do not modified state volume _lock_acquire(&s_volume_lock); s_volume = abs_volume = (volume * 100) / 127; _lock_release(&s_volume_lock); - (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); + (*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume); } -static void volume_set_by_local_host(int value, bool is_step) -{ - _lock_acquire(&s_volume_lock); - s_volume = is_step ? s_volume + value : value; - if (s_volume > 127) s_volume = 127; - else if (s_volume < 0) s_volume = 0; - if (abs_volume >= 0) abs_volume = s_volume; - else sink_volume = s_volume; - _lock_release(&s_volume_lock); - if(sys_state->bt_sink_volume != s_volume){ +static void volume_set_by_local_host(int value, bool is_step) { + _lock_acquire(&s_volume_lock); + s_volume = is_step ? s_volume + value : value; + if(s_volume > 127) + s_volume = 127; + else if(s_volume < 0) + s_volume = 0; + if(abs_volume >= 0) + abs_volume = s_volume; + else + sink_volume = s_volume; + _lock_release(&s_volume_lock); + if(sys_state->bt_sink_volume != s_volume) { sys_state->bt_sink_volume = s_volume; config_raise_state_changed(); } - - if (s_volume_notify) { + + if(s_volume_notify) { esp_avrc_rn_param_t rn_param; rn_param.volume = s_volume; esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_CHANGED, &rn_param); @@ -521,15 +511,14 @@ static void volume_set_by_local_host(int value, bool is_step) } } -static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param) -{ +static void bt_av_hdl_avrc_tg_evt(uint16_t event, void* p_param) { ESP_LOGD(BT_RC_TG_TAG, "%s evt %d", __func__, event); - esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(p_param); - switch (event) { + esp_avrc_tg_cb_param_t* rc = (esp_avrc_tg_cb_param_t*)(p_param); + switch(event) { case ESP_AVRC_TG_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGD(BT_RC_TG_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + uint8_t* bda = rc->conn_stat.remote_bda; + ESP_LOGD(BT_RC_TG_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", rc->conn_stat.connected, bda[0], bda[1], bda[2], + bda[3], bda[4], bda[5]); break; } case ESP_AVRC_TG_PASSTHROUGH_CMD_EVT: { @@ -543,7 +532,7 @@ static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param) } case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: { ESP_LOGD(BT_RC_TG_TAG, "AVRC register event notification: %d, param: 0x%x", rc->reg_ntf.event_id, rc->reg_ntf.event_parameter); - if (rc->reg_ntf.event_id == ESP_AVRC_RN_VOLUME_CHANGE) { + if(rc->reg_ntf.event_id == ESP_AVRC_RN_VOLUME_CHANGE) { s_volume_notify = true; esp_avrc_rn_param_t rn_param; rn_param.volume = s_volume; @@ -561,62 +550,54 @@ static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param) } } -void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb) -{ - bt_app_a2d_cmd_cb = cmd_handler; - cmd_handler_chain = cmd_cb; - bt_app_a2d_data_cb = data_cb; - sys_services_bt_sink * bt_sink; - if(!sys_services_config_BTSINK(bt_sink)){ - return; - } - char pin_code[ESP_BT_PIN_CODE_LEN+1] = "1234\0"; - - // create task and run event loop +void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb) { + bt_app_a2d_cmd_cb = cmd_handler; + cmd_handler_chain = cmd_cb; + bt_app_a2d_data_cb = data_cb; + sys_services_bt_sink* bt_sink; + if(!sys_services_config_BTSINK(bt_sink)) { return; } + char pin_code[ESP_BT_PIN_CODE_LEN + 1] = "1234\0"; + + // create task and run event loop bt_app_task_start_up(bt_av_hdl_stack_evt); - - sink_volume = sys_state->bt_sink_volume; - + + sink_volume = sys_state->bt_sink_volume; + /* * Set default parameters for Legacy Pairing */ esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED; - strncpy(pin_code,bt_sink->pin,sizeof(pin_code)); - if( strlen(bt_sink->pin)>ESP_BT_PIN_CODE_LEN){ + strncpy(pin_code, bt_sink->pin, sizeof(pin_code)); + if(strlen(bt_sink->pin) > ESP_BT_PIN_CODE_LEN) { - ESP_LOGW(BT_AV_TAG, "BT Sink pin code [%s] too long. ", bt_sink->pin); - pin_code[ESP_BT_PIN_CODE_LEN] = '\0'; - ESP_LOGW(BT_AV_TAG, "BT Sink pin truncated code [%s]. ", pin_code); + ESP_LOGW(BT_AV_TAG, "BT Sink pin code [%s] too long. ", bt_sink->pin); + pin_code[ESP_BT_PIN_CODE_LEN] = '\0'; + ESP_LOGW(BT_AV_TAG, "BT Sink pin truncated code [%s]. ", pin_code); } esp_bt_pin_code_t esp_pin_code; - bool bError=false; - memset(esp_pin_code, 0x00, sizeof(esp_pin_code) ); + bool bError = false; + memset(esp_pin_code, 0x00, sizeof(esp_pin_code)); ESP_LOGW(BT_AV_TAG, "BT Sink pin code is: [%s] ", pin_code); - for(int i=0;i '9' ) { - ESP_LOGE(BT_AV_TAG,"Invalid number found in sequence"); - bError=true; - } - esp_pin_code[i]= pin_code[i]; + for(int i = 0; i < strlen(pin_code); i++) { + if(pin_code[i] < '0' || pin_code[i] > '9') { + ESP_LOGE(BT_AV_TAG, "Invalid number found in sequence"); + bError = true; + } + esp_pin_code[i] = pin_code[i]; } - - if (bError) memcpy(esp_pin_code, "1234", 4); - esp_bt_gap_set_pin(pin_type, strlen(pin_code), esp_pin_code); - + + if(bError) memcpy(esp_pin_code, "1234", 4); + esp_bt_gap_set_pin(pin_type, strlen(pin_code), esp_pin_code); } -void bt_sink_deinit(void) -{ - bt_app_task_shut_down(); -} +void bt_sink_deinit(void) { bt_app_task_shut_down(); } -static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) -{ - switch (event) { +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t* param) { + switch(event) { case ESP_BT_GAP_AUTH_CMPL_EVT: { - if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + if(param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { ESP_LOGD(BT_AV_TAG, "authentication success: %s", param->auth_cmpl.device_name); esp_log_buffer_hex(BT_AV_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); } else { @@ -625,7 +606,7 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa break; } -#if (CONFIG_BT_SSP_ENABLED == true) +#if(CONFIG_BT_SSP_ENABLED == true) case ESP_BT_GAP_CFM_REQ_EVT: ESP_LOGD(BT_AV_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); @@ -646,20 +627,19 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa return; } -static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) -{ +static void bt_av_hdl_stack_evt(uint16_t event, void* p_param) { ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event); - switch (event) { + switch(event) { case BT_APP_EVT_STACK_UP: { /* set up device name */ - esp_bt_dev_set_device_name(strlen(platform->names.bluetooth)>0?platform->names.bluetooth:platform->names.device); + esp_bt_dev_set_device_name(strlen(platform->names.bluetooth) > 0 ? platform->names.bluetooth : platform->names.device); esp_bt_gap_register_callback(bt_app_gap_cb); /* initialize AVRCP controller */ esp_avrc_ct_init(); esp_avrc_ct_register_callback(bt_app_rc_ct_cb); /* initialize AVRCP target */ - assert (esp_avrc_tg_init() == ESP_OK); + assert(esp_avrc_tg_init() == ESP_OK); esp_avrc_tg_register_callback(bt_app_rc_tg_cb); esp_avrc_rn_evt_cap_mask_t evt_set = {0}; @@ -680,7 +660,3 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) break; } } - - - - diff --git a/components/driver_bt/bt_app_sink.h b/components/driver_bt/bt_app_sink.h index d02aa51c..f6e173e3 100644 --- a/components/driver_bt/bt_app_sink.h +++ b/components/driver_bt/bt_app_sink.h @@ -12,11 +12,22 @@ #include #include "bt_app_core.h" -typedef enum { BT_SINK_CONNECTED, BT_SINK_DISCONNECTED, BT_SINK_AUDIO_STARTED, BT_SINK_AUDIO_STOPPED, BT_SINK_PLAY, BT_SINK_STOP, BT_SINK_PAUSE, - BT_SINK_RATE, BT_SINK_VOLUME, BT_SINK_METADATA, BT_SINK_PROGRESS } bt_sink_cmd_t; - +typedef enum { + BT_SINK_CONNECTED, + BT_SINK_DISCONNECTED, + BT_SINK_AUDIO_STARTED, + BT_SINK_AUDIO_STOPPED, + BT_SINK_PLAY, + BT_SINK_STOP, + BT_SINK_PAUSE, + BT_SINK_RATE, + BT_SINK_VOLUME, + BT_SINK_METADATA, + BT_SINK_PROGRESS +} bt_sink_cmd_t; + typedef bool (*bt_cmd_vcb_t)(bt_sink_cmd_t cmd, va_list args); -typedef void (*bt_data_cb_t)(const uint8_t *data, uint32_t len); +typedef void (*bt_data_cb_t)(const uint8_t* data, uint32_t len); /** * @brief init sink mode (need to be provided) diff --git a/components/driver_bt/bt_app_source.c b/components/driver_bt/bt_app_source.c index 998f9f18..ac697e4a 100644 --- a/components/driver_bt/bt_app_source.c +++ b/components/driver_bt/bt_app_source.c @@ -24,195 +24,187 @@ #include "Status.pb.h" #include "bootstate.h" - -static const char * TAG = "bt_app_source"; -static const char * BT_RC_CT_TAG="RCCT"; -extern int32_t output_bt_data(uint8_t *data, int32_t len); -extern void output_bt_tick(void); -extern void output_bt_stop(void); -extern void output_bt_start(void); -extern char* output_state_str(void); -extern bool output_stopped(void); +static const char* TAG = "bt_app_source"; +static const char* BT_RC_CT_TAG = "RCCT"; +extern int32_t output_bt_data(uint8_t* data, int32_t len); +extern void output_bt_tick(void); +extern void output_bt_stop(void); +extern void output_bt_start(void); +extern char* output_state_str(void); +extern bool output_stopped(void); extern sys_squeezelite_config* get_profile(const char* name); +static void bt_app_av_state_connecting(uint16_t event, void* param); +static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t* param); +sys_squeezelite_bt* out_bt = NULL; -static void bt_app_av_state_connecting(uint16_t event, void *param); -static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param); -sys_squeezelite_bt * out_bt = NULL; - - -#define BT_APP_HEART_BEAT_EVT (0xff00) +#define BT_APP_HEART_BEAT_EVT (0xff00) // AVRCP used transaction label -#define APP_RC_CT_TL_GET_CAPS (0) -#define APP_RC_CT_TL_RN_VOLUME_CHANGE (1) +#define APP_RC_CT_TL_GET_CAPS (0) +#define APP_RC_CT_TL_RN_VOLUME_CHANGE (1) #define PEERS_LIST_MAINTAIN_RESET -129 #define PEERS_LIST_MAINTAIN_PURGE -129 /// handler for bluetooth stack enabled events -static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); +static void bt_av_hdl_stack_evt(uint16_t event, void* p_param); /// callback function for A2DP source -static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t* param); /// callback function for AVRCP controller -static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param); +static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t* param); /// avrc CT event handler -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param); +static void bt_av_hdl_avrc_ct_evt(uint16_t event, void* p_param); /// callback function for A2DP source audio data stream static void a2d_app_heart_beat(TimerHandle_t timer); /// A2DP application state machine -static void bt_app_av_sm_hdlr(uint16_t event, void *param); +static void bt_app_av_sm_hdlr(uint16_t event, void* param); /* A2DP application state machine handler for each state */ -static void bt_app_av_state_unconnected(uint16_t event, void *param); -static void bt_app_av_state_connecting(uint16_t event, void *param); -static void bt_app_av_state_connected(uint16_t event, void *param); -static void bt_app_av_state_disconnecting(uint16_t event, void *param); -static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param); -static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *param); -static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t *param); -static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_t *param); -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter); +static void bt_app_av_state_unconnected(uint16_t event, void* param); +static void bt_app_av_state_connecting(uint16_t event, void* param); +static void bt_app_av_state_connected(uint16_t event, void* param); +static void bt_app_av_state_disconnecting(uint16_t event, void* param); +static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t* param); +static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t* param); +static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t* param); +static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_t* param); +static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t* event_parameter); static esp_bd_addr_t s_peer_bda = {0}; static uint8_t s_peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; sys_status_av_states bt_app_source_a2d_state = sys_status_av_states_A_IDLE; sys_status_media_states bt_app_source_media_state = sys_status_media_states_M_IDLE; static uint32_t s_pkt_cnt = 0; -static TimerHandle_t s_tmr=NULL; -static int prev_duration=10000; +static TimerHandle_t s_tmr = NULL; +static int prev_duration = 10000; static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; static int s_connecting_intv = 0; -cJSON * peers_list=NULL; +cJSON* peers_list = NULL; static struct { - char * sink_name; -} squeezelite_conf; + char* sink_name; +} squeezelite_conf; -static cJSON * peers_list_get_entry(const char * s_peer_bdname){ - cJSON * element=NULL; - cJSON_ArrayForEach(element,peers_list){ - cJSON * name = cJSON_GetObjectItem(element,"name"); - if(name && !strcmp(cJSON_GetStringValue(name),s_peer_bdname)){ - ESP_LOGV(TAG,"Entry name %s found in current scan list", s_peer_bdname); +static cJSON* peers_list_get_entry(const char* s_peer_bdname) { + cJSON* element = NULL; + cJSON_ArrayForEach(element, peers_list) { + cJSON* name = cJSON_GetObjectItem(element, "name"); + if(name && !strcmp(cJSON_GetStringValue(name), s_peer_bdname)) { + ESP_LOGV(TAG, "Entry name %s found in current scan list", s_peer_bdname); return element; } } - ESP_LOGV(TAG,"Entry name %s NOT found in current scan list", s_peer_bdname); + ESP_LOGV(TAG, "Entry name %s NOT found in current scan list", s_peer_bdname); return NULL; } -static void peers_list_reset(){ - cJSON * element=NULL; - cJSON_ArrayForEach(element,peers_list){ - cJSON * rssi = cJSON_GetObjectItem(element,"rssi"); - if(rssi){ +static void peers_list_reset() { + cJSON* element = NULL; + cJSON_ArrayForEach(element, peers_list) { + cJSON* rssi = cJSON_GetObjectItem(element, "rssi"); + if(rssi) { rssi->valuedouble = -129; rssi->valueint = -129; } } } -static void peers_list_purge(){ - cJSON * element=NULL; - cJSON_ArrayForEach(element,peers_list){ - cJSON * rssi_val = cJSON_GetObjectItem(element,"rssi"); - if(rssi_val && rssi_val->valuedouble == -129){ - cJSON * name = cJSON_GetObjectItem(element,"name"); - ESP_LOGV(TAG,"Purging %s", cJSON_GetStringValue(name)?cJSON_GetStringValue(name):"Unknown"); - cJSON_DetachItemViaPointer(peers_list,element); +static void peers_list_purge() { + cJSON* element = NULL; + cJSON_ArrayForEach(element, peers_list) { + cJSON* rssi_val = cJSON_GetObjectItem(element, "rssi"); + if(rssi_val && rssi_val->valuedouble == -129) { + cJSON* name = cJSON_GetObjectItem(element, "name"); + ESP_LOGV(TAG, "Purging %s", cJSON_GetStringValue(name) ? cJSON_GetStringValue(name) : "Unknown"); + cJSON_DetachItemViaPointer(peers_list, element); cJSON_Delete(element); } - } + } } -static cJSON * peers_list_create_entry(const char * s_peer_bdname, int32_t rssi){ - cJSON * entry = cJSON_CreateObject(); - cJSON_AddStringToObject(entry,"name",s_peer_bdname); - cJSON_AddNumberToObject(entry,"rssi",rssi); +static cJSON* peers_list_create_entry(const char* s_peer_bdname, int32_t rssi) { + cJSON* entry = cJSON_CreateObject(); + cJSON_AddStringToObject(entry, "name", s_peer_bdname); + cJSON_AddNumberToObject(entry, "rssi", rssi); return entry; } -static void peers_list_update_add(const char * s_peer_bdname, int32_t rssi){ - cJSON * element= peers_list_get_entry(s_peer_bdname); - if(element){ - cJSON * rssi_val = cJSON_GetObjectItem(element,"rssi"); - if(rssi_val && rssi_val->valuedouble != rssi){ - ESP_LOGV(TAG,"Updating BT Sink Device: %s rssi to %i", s_peer_bdname,rssi); +static void peers_list_update_add(const char* s_peer_bdname, int32_t rssi) { + cJSON* element = peers_list_get_entry(s_peer_bdname); + if(element) { + cJSON* rssi_val = cJSON_GetObjectItem(element, "rssi"); + if(rssi_val && rssi_val->valuedouble != rssi) { + ESP_LOGV(TAG, "Updating BT Sink Device: %s rssi to %i", s_peer_bdname, rssi); rssi_val->valuedouble = rssi; rssi_val->valueint = rssi; } - } - else { - ESP_LOGI(TAG,"Found BT Sink Device: %s rssi is %i", s_peer_bdname,rssi); - element = peers_list_create_entry( s_peer_bdname, rssi); - cJSON_AddItemToArray(peers_list,element); + } else { + ESP_LOGI(TAG, "Found BT Sink Device: %s rssi is %i", s_peer_bdname, rssi); + element = peers_list_create_entry(s_peer_bdname, rssi); + cJSON_AddItemToArray(peers_list, element); } } -static void peers_list_maintain(const char * s_peer_bdname, int32_t rssi){ - if(!peers_list){ - ESP_LOGV(TAG,"Initializing BT peers list"); - peers_list=cJSON_CreateArray(); +static void peers_list_maintain(const char* s_peer_bdname, int32_t rssi) { + if(!peers_list) { + ESP_LOGV(TAG, "Initializing BT peers list"); + peers_list = cJSON_CreateArray(); } - if(rssi==PEERS_LIST_MAINTAIN_RESET){ - ESP_LOGV(TAG,"Resetting BT peers list"); + if(rssi == PEERS_LIST_MAINTAIN_RESET) { + ESP_LOGV(TAG, "Resetting BT peers list"); peers_list_reset(); - } - else if(rssi==PEERS_LIST_MAINTAIN_PURGE){ - ESP_LOGV(TAG,"Purging BT peers list"); + } else if(rssi == PEERS_LIST_MAINTAIN_PURGE) { + ESP_LOGV(TAG, "Purging BT peers list"); peers_list_purge(); } if(s_peer_bdname) { - ESP_LOGV(TAG,"Adding/Updating peer %s rssi %i", s_peer_bdname,rssi); + ESP_LOGV(TAG, "Adding/Updating peer %s rssi %i", s_peer_bdname, rssi); peers_list_update_add(s_peer_bdname, rssi); } - char * list_json = cJSON_Print(peers_list); - if(list_json){ + char* list_json = cJSON_Print(peers_list); + if(list_json) { messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_BT, list_json); - ESP_LOGV(TAG,"%s", list_json); + ESP_LOGV(TAG, "%s", list_json); free(list_json); - } + } } -sys_status_av_states bt_app_source_get_a2d_state(){ - if(!is_recovery_running){ +sys_status_av_states bt_app_source_get_a2d_state() { + if(!is_recovery_running) { // if we are in recovery mode, don't log BT status - ESP_LOGD(TAG,"a2dp status: %u = %s", bt_app_source_a2d_state, sys_status_av_states_name(bt_app_source_a2d_state)); + ESP_LOGD(TAG, "a2dp status: %u = %s", bt_app_source_a2d_state, sys_status_av_states_name(bt_app_source_a2d_state)); } return bt_app_source_a2d_state; } - -sys_status_media_states bt_app_source_get_media_state(){ - ESP_LOGD(TAG,"media state : %s ", sys_status_media_states_name(bt_app_source_media_state)); +sys_status_media_states bt_app_source_get_media_state() { + ESP_LOGD(TAG, "media state : %s ", sys_status_media_states_name(bt_app_source_media_state)); return bt_app_source_media_state; } -void set_app_source_state(int new_state){ - if(bt_app_source_a2d_state!=new_state){ +void set_app_source_state(int new_state) { + if(bt_app_source_a2d_state != new_state) { ESP_LOGD(TAG, "Updating state from %s to %s", sys_status_av_states_name(bt_app_source_a2d_state), sys_status_av_states_name(new_state)); - bt_app_source_a2d_state=new_state; + bt_app_source_a2d_state = new_state; } } -void set_a2dp_media_state(int new_state){ - if(bt_app_source_media_state!=new_state){ - bt_app_source_media_state=new_state; - } +void set_a2dp_media_state(int new_state) { + if(bt_app_source_media_state != new_state) { bt_app_source_media_state = new_state; } } void hal_bluetooth_init() { sys_squeezelite_config* config = get_profile(NULL); // get the active profile sys_squeezelite_bt* out_bt = (config && config->has_output_bt) ? &config->output_bt : NULL; - if (!out_bt) { + if(!out_bt) { ESP_LOGD(TAG, "Bluetooth not configured"); return; } - if (strlen(out_bt->sink_name) == 0) { + if(strlen(out_bt->sink_name) == 0) { ESP_LOGE(TAG, "Sink name not configured!"); return; } @@ -228,7 +220,7 @@ void hal_bluetooth_init() { esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; uint8_t pin_code_len; uint8_t* pin_code; - if (strlen(out_bt->pin) == 0) { + if(strlen(out_bt->pin) == 0) { pin_code = (uint8_t*)"0000"; pin_code_len = 4; } else { @@ -238,290 +230,261 @@ void hal_bluetooth_init() { esp_bt_gap_set_pin(pin_type, pin_code_len, pin_code); } -void hal_bluetooth_stop(void) { - bt_app_task_shut_down(); -} +void hal_bluetooth_stop(void) { bt_app_task_shut_down(); } -static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) -{ +static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t* param) { bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL); } -static void handle_bt_gap_pin_req(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param){ +static void handle_bt_gap_pin_req(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t* param) { uint8_t pinlen; - char *pin_str; - if(strlen(out_bt->pin) == 0){ + char* pin_str; + if(strlen(out_bt->pin) == 0) { pin_str = "0000"; - } - else { - pin_str = out_bt->pin; + } else { + pin_str = out_bt->pin; } pinlen = strlen(pin_str); - if (pin_str && ((!param->pin_req.min_16_digit && pinlen==4) || (param->pin_req.min_16_digit && pinlen==16))) { - ESP_LOGI(TAG,"Input pin code %s: ",pin_str); + if(pin_str && ((!param->pin_req.min_16_digit && pinlen == 4) || (param->pin_req.min_16_digit && pinlen == 16))) { + ESP_LOGI(TAG, "Input pin code %s: ", pin_str); esp_bt_pin_code_t pin_code; - for (size_t i = 0; i < pinlen; i++) - { - pin_code[i] = pin_str[i]; - } + for(size_t i = 0; i < pinlen; i++) { pin_code[i] = pin_str[i]; } esp_bt_gap_pin_reply(param->pin_req.bda, true, pinlen, pin_code); - } - else { - if(pinlen>0){ - ESP_LOGW(TAG,"Pin length: %u does not match the length expected by the device: %u", pinlen, ((param->pin_req.min_16_digit)?16:4)); - } - else { + } else { + if(pinlen > 0) { + ESP_LOGW(TAG, "Pin length: %u does not match the length expected by the device: %u", pinlen, ((param->pin_req.min_16_digit) ? 16 : 4)); + } else { ESP_LOGW(TAG, "No security Pin provided. Trying with default pins."); } - if (param->pin_req.min_16_digit) { - ESP_LOGI(TAG,"Input pin code: 0000 0000 0000 0000"); + if(param->pin_req.min_16_digit) { + ESP_LOGI(TAG, "Input pin code: 0000 0000 0000 0000"); esp_bt_pin_code_t pin_code = {0}; esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); } else { - ESP_LOGI(TAG,"Input pin code: 1234"); + ESP_LOGI(TAG, "Input pin code: 1234"); esp_bt_pin_code_t pin_code; pin_code[0] = '1'; pin_code[1] = '2'; pin_code[2] = '3'; pin_code[3] = '4'; esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); - } + } } } -static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) -{ +static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t* param) { - switch (event) { + switch(event) { case ESP_BT_GAP_DISC_RES_EVT: { filter_inquiry_scan_result(param); break; } case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: { - - if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) { + + if(param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) { peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_PURGE); - if (bt_app_source_a2d_state == sys_status_av_states_A_DISCOVERED) { - set_app_source_state(sys_status_av_states_A_CONNECTING); - ESP_LOGI(TAG,"Discovery completed. Ready to start connecting to %s. ", s_peer_bdname); + if(bt_app_source_a2d_state == sys_status_av_states_A_DISCOVERED) { + set_app_source_state(sys_status_av_states_A_CONNECTING); + ESP_LOGI(TAG, "Discovery completed. Ready to start connecting to %s. ", s_peer_bdname); esp_a2d_source_connect(s_peer_bda); } else { // not discovered, continue to discover ESP_LOGI(TAG, "Device discovery failed, continue to discover..."); esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0); } - } else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) { + } else if(param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) { ESP_LOGI(TAG, "Discovery started."); - peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_RESET); + peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_RESET); } break; } case ESP_BT_GAP_RMT_SRVCS_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_BT_GAP_RMT_SRVCS_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_BT_GAP_RMT_SRVCS_EVT)); + break; case ESP_BT_GAP_RMT_SRVC_REC_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_BT_GAP_RMT_SRVC_REC_EVT)); + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_BT_GAP_RMT_SRVC_REC_EVT)); break; case ESP_BT_GAP_AUTH_CMPL_EVT: { - if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { - ESP_LOGI(TAG,"authentication success: %s", param->auth_cmpl.device_name); + if(param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(TAG, "authentication success: %s", param->auth_cmpl.device_name); //esp_log_buffer_hex(param->auth_cmpl.bda, ESP_BD_ADDR_LEN); } else { - ESP_LOGE(TAG,"authentication failed, status:%d", param->auth_cmpl.stat); + ESP_LOGE(TAG, "authentication failed, status:%d", param->auth_cmpl.stat); } break; } - case ESP_BT_GAP_PIN_REQ_EVT: + case ESP_BT_GAP_PIN_REQ_EVT: handle_bt_gap_pin_req(event, param); break; -#if (CONFIG_BT_SSP_ENABLED == true) +#if(CONFIG_BT_SSP_ENABLED == true) case ESP_BT_GAP_CFM_REQ_EVT: - ESP_LOGI(TAG,"ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); + ESP_LOGI(TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); break; case ESP_BT_GAP_KEY_NOTIF_EVT: - ESP_LOGI(TAG,"ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); + ESP_LOGI(TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); break; - ESP_LOGI(TAG,"ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); + ESP_LOGI(TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); break; #endif default: { - ESP_LOGI(TAG,"event: %d", event); + ESP_LOGI(TAG, "event: %d", event); break; } } return; } -int heart_beat_delay[] = { - 1000, - 1000, - 1000, - 1000, - 10000, - 500, - 1000 -}; +int heart_beat_delay[] = {1000, 1000, 1000, 1000, 10000, 500, 1000}; -static void a2d_app_heart_beat(TimerHandle_t timer) -{ +static void a2d_app_heart_beat(TimerHandle_t timer) { (void)timer; bt_app_work_dispatch(bt_app_av_sm_hdlr, BT_APP_HEART_BEAT_EVT, NULL, 0, NULL); - int tmrduration=heart_beat_delay[bt_app_source_a2d_state]; - if(prev_duration!=tmrduration){ + int tmrduration = heart_beat_delay[bt_app_source_a2d_state]; + if(prev_duration != tmrduration) { xTimerChangePeriod(s_tmr, pdMS_TO_TICKS(tmrduration), portMAX_DELAY); - ESP_LOGD(TAG,"New heartbeat is %u",tmrduration); - prev_duration=tmrduration; - } - else { - ESP_LOGD(TAG,"Starting Heart beat timer for %ums",tmrduration); + ESP_LOGD(TAG, "New heartbeat is %u", tmrduration); + prev_duration = tmrduration; + } else { + ESP_LOGD(TAG, "Starting Heart beat timer for %ums", tmrduration); } xTimerStart(s_tmr, portMAX_DELAY); } -static const char * conn_state_str(esp_a2d_connection_state_t state){ - char * statestr = "Unknown"; - switch (state) - { - case ESP_A2D_CONNECTION_STATE_DISCONNECTED: - statestr=STR(ESP_A2D_CONNECTION_STATE_DISCONNECTED); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTING: - statestr=STR(ESP_A2D_CONNECTION_STATE_CONNECTING); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTED: - statestr=STR(ESP_A2D_CONNECTION_STATE_CONNECTED); - break; - case ESP_A2D_CONNECTION_STATE_DISCONNECTING: - statestr=STR(ESP_A2D_CONNECTION_STATE_DISCONNECTING); - break; - default: - break; - } +static const char* conn_state_str(esp_a2d_connection_state_t state) { + char* statestr = "Unknown"; + switch(state) { + case ESP_A2D_CONNECTION_STATE_DISCONNECTED: + statestr = STR(ESP_A2D_CONNECTION_STATE_DISCONNECTED); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTING: + statestr = STR(ESP_A2D_CONNECTION_STATE_CONNECTING); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTED: + statestr = STR(ESP_A2D_CONNECTION_STATE_CONNECTED); + break; + case ESP_A2D_CONNECTION_STATE_DISCONNECTING: + statestr = STR(ESP_A2D_CONNECTION_STATE_DISCONNECTING); + break; + default: + break; + } return statestr; } -static void unexpected_connection_state(int from, esp_a2d_connection_state_t to) -{ - ESP_LOGW(TAG,"Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", sys_status_av_states_name(from), from,conn_state_str(to), to); +static void unexpected_connection_state(int from, esp_a2d_connection_state_t to) { + ESP_LOGW(TAG, "Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", sys_status_av_states_name(from), from, + conn_state_str(to), to); } -static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param){ +static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t* param) { ESP_LOGV(TAG, "A2DP Event while unconnected "); - switch (param->conn_stat.state) - { - case ESP_A2D_CONNECTION_STATE_DISCONNECTED: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTING: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTED: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - ESP_LOGE(TAG,"Connection state event received while status was unconnected. Routing message to connecting state handler. State : %u",param->conn_stat.state); - if (param->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){ - handle_connect_state_connecting(event, param); - } + switch(param->conn_stat.state) { + case ESP_A2D_CONNECTION_STATE_DISCONNECTED: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTING: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTED: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + ESP_LOGE(TAG, "Connection state event received while status was unconnected. Routing message to connecting state handler. State : %u", + param->conn_stat.state); + if(param->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) { handle_connect_state_connecting(event, param); } + break; + case ESP_A2D_CONNECTION_STATE_DISCONNECTING: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + default: break; - case ESP_A2D_CONNECTION_STATE_DISCONNECTING: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - default: - break; - } - -} - -static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *param){ - ESP_LOGV(TAG, "A2DP connection state event : %s ",conn_state_str(param->conn_stat.state)); - - switch (param->conn_stat.state) - { - case ESP_A2D_CONNECTION_STATE_DISCONNECTED: - if(param->conn_stat.disc_rsn!=ESP_A2D_DISC_RSN_NORMAL){ - ESP_LOGE(TAG,"A2DP had an abnormal disconnect event"); - } - else { - ESP_LOGW(TAG,"A2DP connect unsuccessful"); - } - set_app_source_state(sys_status_av_states_A_UNCONNECTED); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTING: - break; - case ESP_A2D_CONNECTION_STATE_CONNECTED: - set_app_source_state(sys_status_av_states_A_CONNECTED); - set_a2dp_media_state(sys_status_media_states_M_IDLE); - ESP_LOGD(TAG,"Setting scan mode to ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE"); - esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); - ESP_LOGD(TAG,"Done setting scan mode. App state is now CONNECTED and media state IDLE."); - break; - case ESP_A2D_CONNECTION_STATE_DISCONNECTING: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - set_app_source_state(sys_status_av_states_A_CONNECTING); - break; - default: - break; } } -static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t *param){ + +static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t* param) { + ESP_LOGV(TAG, "A2DP connection state event : %s ", conn_state_str(param->conn_stat.state)); + + switch(param->conn_stat.state) { + case ESP_A2D_CONNECTION_STATE_DISCONNECTED: + if(param->conn_stat.disc_rsn != ESP_A2D_DISC_RSN_NORMAL) { + ESP_LOGE(TAG, "A2DP had an abnormal disconnect event"); + } else { + ESP_LOGW(TAG, "A2DP connect unsuccessful"); + } + set_app_source_state(sys_status_av_states_A_UNCONNECTED); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTING: + break; + case ESP_A2D_CONNECTION_STATE_CONNECTED: + set_app_source_state(sys_status_av_states_A_CONNECTED); + set_a2dp_media_state(sys_status_media_states_M_IDLE); + ESP_LOGD(TAG, "Setting scan mode to ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE"); + esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); + ESP_LOGD(TAG, "Done setting scan mode. App state is now CONNECTED and media state IDLE."); + break; + case ESP_A2D_CONNECTION_STATE_DISCONNECTING: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + set_app_source_state(sys_status_av_states_A_CONNECTING); + break; + default: + break; + } +} +static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t* param) { ESP_LOGV(TAG, "A2DP Event while connected "); - switch (param->conn_stat.state) - { - case ESP_A2D_CONNECTION_STATE_DISCONNECTED: - ESP_LOGW(TAG,"a2dp disconnected"); - set_app_source_state(sys_status_av_states_A_UNCONNECTED); - esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTING: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTED: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - case ESP_A2D_CONNECTION_STATE_DISCONNECTING: - set_app_source_state(sys_status_av_states_A_DISCONNECTING); + switch(param->conn_stat.state) { + case ESP_A2D_CONNECTION_STATE_DISCONNECTED: + ESP_LOGW(TAG, "a2dp disconnected"); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTING: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTED: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + case ESP_A2D_CONNECTION_STATE_DISCONNECTING: + set_app_source_state(sys_status_av_states_A_DISCONNECTING); - break; - default: - break; + break; + default: + break; } } -static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_t *param){ +static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_t* param) { ESP_LOGV(TAG, "A2DP Event while disconnecting "); - switch (param->conn_stat.state) - { - case ESP_A2D_CONNECTION_STATE_DISCONNECTED: - ESP_LOGI(TAG,"a2dp disconnected"); - set_app_source_state(sys_status_av_states_A_UNCONNECTED); - esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTING: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - case ESP_A2D_CONNECTION_STATE_CONNECTED: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - case ESP_A2D_CONNECTION_STATE_DISCONNECTING: - unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); - break; - default: - break; + switch(param->conn_stat.state) { + case ESP_A2D_CONNECTION_STATE_DISCONNECTED: + ESP_LOGI(TAG, "a2dp disconnected"); + set_app_source_state(sys_status_av_states_A_UNCONNECTED); + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTING: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + case ESP_A2D_CONNECTION_STATE_CONNECTED: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + case ESP_A2D_CONNECTION_STATE_DISCONNECTING: + unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state); + break; + default: + break; } - } -static void bt_app_av_sm_hdlr(uint16_t event, void *param) -{ - ESP_LOGV(TAG,"bt_app_av_sm_hdlr.%s a2d state: %s", event==BT_APP_HEART_BEAT_EVT?"Heart Beat.":"",sys_status_av_states_name(bt_app_source_a2d_state)); - switch (bt_app_source_a2d_state) { +static void bt_app_av_sm_hdlr(uint16_t event, void* param) { + ESP_LOGV(TAG, "bt_app_av_sm_hdlr.%s a2d state: %s", event == BT_APP_HEART_BEAT_EVT ? "Heart Beat." : "", + sys_status_av_states_name(bt_app_source_a2d_state)); + switch(bt_app_source_a2d_state) { case sys_status_av_states_A_DISCOVERING: - ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", sys_status_av_states_name(bt_app_source_a2d_state), event, output_state_str()); - break; + ESP_LOGV(TAG, "state %s, evt 0x%x, output state: %s", sys_status_av_states_name(bt_app_source_a2d_state), event, output_state_str()); + break; case sys_status_av_states_A_DISCOVERED: - ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", sys_status_av_states_name(bt_app_source_a2d_state), event, output_state_str()); + ESP_LOGV(TAG, "state %s, evt 0x%x, output state: %s", sys_status_av_states_name(bt_app_source_a2d_state), event, output_state_str()); break; case sys_status_av_states_A_UNCONNECTED: bt_app_av_state_unconnected(event, param); @@ -536,147 +499,127 @@ static void bt_app_av_sm_hdlr(uint16_t event, void *param) bt_app_av_state_disconnecting(event, param); break; default: - ESP_LOGE(TAG,"%s invalid state %d", __func__, bt_app_source_a2d_state); + ESP_LOGE(TAG, "%s invalid state %d", __func__, bt_app_source_a2d_state); break; } } -static char *bda2str(esp_bd_addr_t bda, char *str, size_t size) -{ - if (bda == NULL || str == NULL || size < 18) { - return NULL; - } +static char* bda2str(esp_bd_addr_t bda, char* str, size_t size) { + if(bda == NULL || str == NULL || size < 18) { return NULL; } - uint8_t *p = bda; - sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", - p[0], p[1], p[2], p[3], p[4], p[5]); + uint8_t* p = bda; + sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", p[0], p[1], p[2], p[3], p[4], p[5]); return str; } -static bool get_name_from_eir(uint8_t *eir, uint8_t *bdname, uint8_t *bdname_len) -{ - uint8_t *rmt_bdname = NULL; +static bool get_name_from_eir(uint8_t* eir, uint8_t* bdname, uint8_t* bdname_len) { + uint8_t* rmt_bdname = NULL; uint8_t rmt_bdname_len = 0; - if (!eir) { - return false; - } + if(!eir) { return false; } rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len); - if (!rmt_bdname) { - rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len); - } + if(!rmt_bdname) { rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len); } - if (rmt_bdname) { - if (rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) { - rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN; - } + if(rmt_bdname) { + if(rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) { rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN; } - if (bdname) { + if(bdname) { memcpy(bdname, rmt_bdname, rmt_bdname_len); bdname[rmt_bdname_len] = '\0'; } - if (bdname_len) { - *bdname_len = rmt_bdname_len; - } + if(bdname_len) { *bdname_len = rmt_bdname_len; } return true; } return false; } -static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param) -{ +static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t* param) { char bda_str[18]; uint32_t cod = 0; int32_t rssi = -129; /* invalid value */ - uint8_t *eir = NULL; + uint8_t* eir = NULL; uint8_t nameLen = 0; - esp_bt_gap_dev_prop_t *p; + esp_bt_gap_dev_prop_t* p; memset(bda_str, 0x00, sizeof(bda_str)); - if(bt_app_source_a2d_state != sys_status_av_states_A_DISCOVERING) - { - // Ignore messages that might have been queued already - // when we've discovered the target device. - return; + if(bt_app_source_a2d_state != sys_status_av_states_A_DISCOVERING) { + // Ignore messages that might have been queued already + // when we've discovered the target device. + return; } - memset(s_peer_bdname, 0x00,sizeof(s_peer_bdname)); + memset(s_peer_bdname, 0x00, sizeof(s_peer_bdname)); bda2str(param->disc_res.bda, bda_str, 18); - ESP_LOGV(TAG,"\n=======================\nScanned device: %s",bda_str ); - for (int i = 0; i < param->disc_res.num_prop; i++) { + ESP_LOGV(TAG, "\n=======================\nScanned device: %s", bda_str); + for(int i = 0; i < param->disc_res.num_prop; i++) { p = param->disc_res.prop + i; - switch (p->type) { + switch(p->type) { case ESP_BT_GAP_DEV_PROP_COD: - cod = *(uint32_t *)(p->val); - ESP_LOGV(TAG,"-- Class of Device: 0x%x", cod); + cod = *(uint32_t*)(p->val); + ESP_LOGV(TAG, "-- Class of Device: 0x%x", cod); break; case ESP_BT_GAP_DEV_PROP_RSSI: - rssi = *(int8_t *)(p->val); - ESP_LOGV(TAG,"-- RSSI: %d", rssi); + rssi = *(int8_t*)(p->val); + ESP_LOGV(TAG, "-- RSSI: %d", rssi); break; case ESP_BT_GAP_DEV_PROP_EIR: - eir = (uint8_t *)(p->val); - ESP_LOGV(TAG,"-- EIR: %u", *eir); + eir = (uint8_t*)(p->val); + ESP_LOGV(TAG, "-- EIR: %u", *eir); break; case ESP_BT_GAP_DEV_PROP_BDNAME: nameLen = (p->len > ESP_BT_GAP_MAX_BDNAME_LEN) ? ESP_BT_GAP_MAX_BDNAME_LEN : (uint8_t)p->len; - memcpy(s_peer_bdname, (uint8_t *)(p->val), nameLen); + memcpy(s_peer_bdname, (uint8_t*)(p->val), nameLen); s_peer_bdname[nameLen] = '\0'; - ESP_LOGV(TAG,"-- Name: %s", s_peer_bdname); + ESP_LOGV(TAG, "-- Name: %s", s_peer_bdname); break; default: break; } } - if (!esp_bt_gap_is_valid_cod(cod)){ - /* search for device with MAJOR service class as "rendering" in COD */ - ESP_LOGV(TAG,"--Invalid class of device. Skipping.\n"); - return; - } - else if (!(esp_bt_gap_get_cod_srvc(cod) & (ESP_BT_COD_SRVC_RENDERING | ESP_BT_COD_SRVC_AUDIO))) - { - ESP_LOGV(TAG,"--Not a rendering or audio device. Skipping.\n"); - return; + if(!esp_bt_gap_is_valid_cod(cod)) { + /* search for device with MAJOR service class as "rendering" in COD */ + ESP_LOGV(TAG, "--Invalid class of device. Skipping.\n"); + return; + } else if(!(esp_bt_gap_get_cod_srvc(cod) & (ESP_BT_COD_SRVC_RENDERING | ESP_BT_COD_SRVC_AUDIO))) { + ESP_LOGV(TAG, "--Not a rendering or audio device. Skipping.\n"); + return; } - if (eir) { - ESP_LOGV(TAG,"--Getting details from eir.\n"); + if(eir) { + ESP_LOGV(TAG, "--Getting details from eir.\n"); get_name_from_eir(eir, s_peer_bdname, NULL); - ESP_LOGV(TAG,"--Device name is %s\n",s_peer_bdname); - } - if(strlen((char *)s_peer_bdname)>0) { - peers_list_maintain((const char *)s_peer_bdname, rssi); + ESP_LOGV(TAG, "--Device name is %s\n", s_peer_bdname); } + if(strlen((char*)s_peer_bdname) > 0) { peers_list_maintain((const char*)s_peer_bdname, rssi); } - if (squeezelite_conf.sink_name && strlen(squeezelite_conf.sink_name) >0 && strcmp((char *)s_peer_bdname, squeezelite_conf.sink_name) == 0) { - ESP_LOGI(TAG,"Found our target device. address %s, name %s", bda_str, s_peer_bdname); - memcpy(s_peer_bda, param->disc_res.bda, ESP_BD_ADDR_LEN); + if(squeezelite_conf.sink_name && strlen(squeezelite_conf.sink_name) > 0 && strcmp((char*)s_peer_bdname, squeezelite_conf.sink_name) == 0) { + ESP_LOGI(TAG, "Found our target device. address %s, name %s", bda_str, s_peer_bdname); + memcpy(s_peer_bda, param->disc_res.bda, ESP_BD_ADDR_LEN); set_app_source_state(sys_status_av_states_A_DISCOVERED); esp_bt_gap_cancel_discovery(); } else { - ESP_LOGV(TAG,"Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name?squeezelite_conf.sink_name:"N/A"); + ESP_LOGV(TAG, "Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name ? squeezelite_conf.sink_name : "N/A"); } } -static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) -{ - switch (event) { +static void bt_av_hdl_stack_evt(uint16_t event, void* p_param) { + switch(event) { case BT_APP_EVT_STACK_UP: { - ESP_LOGI(TAG,"BT Stack going up."); + ESP_LOGI(TAG, "BT Stack going up."); /* set up device name */ - if(!out_bt){ - ESP_LOGE(TAG,"Output to bluetooth misconfigured."); + if(!out_bt) { + ESP_LOGE(TAG, "Output to bluetooth misconfigured."); return; } - if(strlen(out_bt->sink_name)==0){ - ESP_LOGE(TAG,"Bluetooth sink name not configured"); + if(strlen(out_bt->sink_name) == 0) { + ESP_LOGE(TAG, "Bluetooth sink name not configured"); return; } - esp_bt_dev_set_device_name(out_bt->sink_name); - - ESP_LOGI(TAG,"Preparing to connect"); + esp_bt_dev_set_device_name(out_bt->sink_name); + + ESP_LOGI(TAG, "Preparing to connect"); /* register GAP callback function */ esp_bt_gap_register_callback(bt_app_gap_cb); @@ -689,7 +632,6 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE); assert(esp_avrc_tg_set_rn_evt_cap(&evt_set) == ESP_OK); - /* initialize A2DP source */ esp_a2d_register_callback(&bt_app_a2d_cb); esp_a2d_source_register_data_callback(&output_bt_data); @@ -699,24 +641,23 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); /* start device discovery */ - ESP_LOGI(TAG,"Starting device discovery..."); + ESP_LOGI(TAG, "Starting device discovery..."); set_app_source_state(sys_status_av_states_A_DISCOVERING); esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0); /* create and start heart beat timer */ int tmr_id = 0; - s_tmr = xTimerCreate("connTmr", pdMS_TO_TICKS(prev_duration), pdFALSE, (void *)tmr_id, a2d_app_heart_beat); + s_tmr = xTimerCreate("connTmr", pdMS_TO_TICKS(prev_duration), pdFALSE, (void*)tmr_id, a2d_app_heart_beat); xTimerStart(s_tmr, portMAX_DELAY); break; } default: - ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event); + ESP_LOGE(TAG, "%s unhandled evt %d", __func__, event); break; } } -static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) -{ - switch (event) { +static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t* param) { + switch(event) { case ESP_AVRC_CT_METADATA_RSP_EVT: case ESP_AVRC_CT_CONNECTION_STATE_EVT: case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: @@ -724,7 +665,7 @@ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t case ESP_AVRC_CT_REMOTE_FEATURES_EVT: case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: { - ESP_LOGD(TAG,"Received %s message", sys_status_avrc_ct_name(event)); + ESP_LOGD(TAG, "Received %s message", sys_status_avrc_ct_name(event)); bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); break; } @@ -733,235 +674,218 @@ static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t break; } } -static void bt_app_av_media_proc(uint16_t event, void *param) -{ - esp_a2d_cb_param_t *a2d = NULL; - switch (bt_app_source_media_state) { +static void bt_app_av_media_proc(uint16_t event, void* param) { + esp_a2d_cb_param_t* a2d = NULL; + switch(bt_app_source_media_state) { case sys_status_media_states_M_IDLE: { - if (event == BT_APP_HEART_BEAT_EVT) { - if(!output_stopped()) - { - ESP_LOGI(TAG,"Output state is %s, Checking if A2DP is ready.", output_state_str()); - esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY); + if(event == BT_APP_HEART_BEAT_EVT) { + if(!output_stopped()) { + ESP_LOGI(TAG, "Output state is %s, Checking if A2DP is ready.", output_state_str()); + esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY); } - } else if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { - a2d = (esp_a2d_cb_param_t *)(param); - if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY && - a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS - ) { - ESP_LOGI(TAG,"a2dp media ready, starting playback!"); - set_a2dp_media_state(sys_status_media_states_M_STARTING); - esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_START); - } + } else if(event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { + a2d = (esp_a2d_cb_param_t*)(param); + if(a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY && a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { + ESP_LOGI(TAG, "a2dp media ready, starting playback!"); + set_a2dp_media_state(sys_status_media_states_M_STARTING); + esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_START); + } } break; } case sys_status_media_states_M_STARTING: { - if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { - a2d = (esp_a2d_cb_param_t *)(param); - if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_START && - a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { - ESP_LOGI(TAG,"a2dp media started successfully."); + if(event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { + a2d = (esp_a2d_cb_param_t*)(param); + if(a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_START && a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { + ESP_LOGI(TAG, "a2dp media started successfully."); output_bt_start(); set_a2dp_media_state(sys_status_media_states_M_STARTED); } else { // not started succesfully, transfer to idle state - ESP_LOGI(TAG,"a2dp media start failed."); + ESP_LOGI(TAG, "a2dp media start failed."); set_a2dp_media_state(sys_status_media_states_M_IDLE); } } break; } case sys_status_media_states_M_STARTED: { - if (event == BT_APP_HEART_BEAT_EVT) { - if(output_stopped()) { - ESP_LOGI(TAG,"Output state is %s. Stopping a2dp media ...", output_state_str()); + if(event == BT_APP_HEART_BEAT_EVT) { + if(output_stopped()) { + ESP_LOGI(TAG, "Output state is %s. Stopping a2dp media ...", output_state_str()); set_a2dp_media_state(sys_status_media_states_M_STOPPING); esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP); } else { - output_bt_tick(); - } + output_bt_tick(); + } } break; } case sys_status_media_states_M_STOPPING: { - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(sys_status_media_states_M_STOPPING)); - if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { - a2d = (esp_a2d_cb_param_t *)(param); - if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_STOP && - a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { - ESP_LOGI(TAG,"a2dp media stopped successfully..."); + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(sys_status_media_states_M_STOPPING)); + if(event == ESP_A2D_MEDIA_CTRL_ACK_EVT) { + a2d = (esp_a2d_cb_param_t*)(param); + if(a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_STOP && a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) { + ESP_LOGI(TAG, "a2dp media stopped successfully..."); output_bt_stop(); - set_a2dp_media_state(sys_status_media_states_M_IDLE); + set_a2dp_media_state(sys_status_media_states_M_IDLE); } else { - ESP_LOGI(TAG,"a2dp media stopping..."); + ESP_LOGI(TAG, "a2dp media stopping..."); esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP); } } break; } - case sys_status_media_states_M_WAIT_DISCONNECT:{ - esp_a2d_source_disconnect(s_peer_bda); - set_app_source_state(sys_status_av_states_A_DISCONNECTING); - ESP_LOGI(TAG,"a2dp disconnecting..."); + case sys_status_media_states_M_WAIT_DISCONNECT: { + esp_a2d_source_disconnect(s_peer_bda); + set_app_source_state(sys_status_av_states_A_DISCONNECTING); + ESP_LOGI(TAG, "a2dp disconnecting..."); } } } -static void bt_app_av_state_unconnected(uint16_t event, void *param) -{ +static void bt_app_av_state_unconnected(uint16_t event, void* param) { ESP_LOGV(TAG, "Handling state unconnected A2DP event"); - switch (event) { + switch(event) { case ESP_A2D_CONNECTION_STATE_EVT: - handle_connect_state_unconnected(event, (esp_a2d_cb_param_t *)param); - break; + handle_connect_state_unconnected(event, (esp_a2d_cb_param_t*)param); + break; case ESP_A2D_AUDIO_STATE_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_STATE_EVT)); + break; case ESP_A2D_AUDIO_CFG_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_CFG_EVT)); + break; case ESP_A2D_MEDIA_CTRL_ACK_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); + break; case BT_APP_HEART_BEAT_EVT: { - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(BT_APP_HEART_BEAT_EVT)); - switch (esp_bluedroid_get_status()) { - case ESP_BLUEDROID_STATUS_UNINITIALIZED: - ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_UNINITIALIZED."); - break; - case ESP_BLUEDROID_STATUS_INITIALIZED: - ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_INITIALIZED."); - break; - case ESP_BLUEDROID_STATUS_ENABLED: - ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_ENABLED."); - break; - default: - break; - } - uint8_t *p = s_peer_bda; - ESP_LOGI(TAG, "a2dp connecting to %s, BT peer: %02x:%02x:%02x:%02x:%02x:%02x",s_peer_bdname,p[0], p[1], p[2], p[3], p[4], p[5]); - if(esp_a2d_source_connect(s_peer_bda)==ESP_OK) { + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(BT_APP_HEART_BEAT_EVT)); + switch(esp_bluedroid_get_status()) { + case ESP_BLUEDROID_STATUS_UNINITIALIZED: + ESP_LOGV(TAG, "BlueDroid Status is ESP_BLUEDROID_STATUS_UNINITIALIZED."); + break; + case ESP_BLUEDROID_STATUS_INITIALIZED: + ESP_LOGV(TAG, "BlueDroid Status is ESP_BLUEDROID_STATUS_INITIALIZED."); + break; + case ESP_BLUEDROID_STATUS_ENABLED: + ESP_LOGV(TAG, "BlueDroid Status is ESP_BLUEDROID_STATUS_ENABLED."); + break; + default: + break; + } + uint8_t* p = s_peer_bda; + ESP_LOGI(TAG, "a2dp connecting to %s, BT peer: %02x:%02x:%02x:%02x:%02x:%02x", s_peer_bdname, p[0], p[1], p[2], p[3], p[4], p[5]); + if(esp_a2d_source_connect(s_peer_bda) == ESP_OK) { set_app_source_state(sys_status_av_states_A_CONNECTING); s_connecting_intv = 0; - } - else { + } else { set_app_source_state(sys_status_av_states_A_UNCONNECTED); - // there was an issue connecting... continue to discover - ESP_LOGE(TAG,"Attempt at connecting failed, restart at discover..."); - esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0); + // there was an issue connecting... continue to discover + ESP_LOGE(TAG, "Attempt at connecting failed, restart at discover..."); + esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0); } break; } default: - ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event); + ESP_LOGE(TAG, "%s unhandled evt %d", __func__, event); break; } } -static void bt_app_av_state_connecting(uint16_t event, void *param) -{ - switch (event) { +static void bt_app_av_state_connecting(uint16_t event, void* param) { + switch(event) { case ESP_A2D_CONNECTION_STATE_EVT: - handle_connect_state_connecting(event, (esp_a2d_cb_param_t *)param); + handle_connect_state_connecting(event, (esp_a2d_cb_param_t*)param); break; case ESP_A2D_AUDIO_STATE_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_STATE_EVT)); + break; case ESP_A2D_AUDIO_CFG_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_CFG_EVT)); + break; case ESP_A2D_MEDIA_CTRL_ACK_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); - break; + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); + break; case BT_APP_HEART_BEAT_EVT: - if (++s_connecting_intv >= 2) { + if(++s_connecting_intv >= 2) { set_app_source_state(sys_status_av_states_A_UNCONNECTED); - ESP_LOGW(TAG,"A2DP Connect time out! Setting state to Unconnected. "); + ESP_LOGW(TAG, "A2DP Connect time out! Setting state to Unconnected. "); s_connecting_intv = 0; } break; default: - ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event); + ESP_LOGE(TAG, "%s unhandled evt %d", __func__, event); break; } } - -static void bt_app_av_state_connected(uint16_t event, void *param) -{ - esp_a2d_cb_param_t *a2d = NULL; - switch (event) { +static void bt_app_av_state_connected(uint16_t event, void* param) { + esp_a2d_cb_param_t* a2d = NULL; + switch(event) { case ESP_A2D_CONNECTION_STATE_EVT: { - handle_connect_state_connected(event, (esp_a2d_cb_param_t *)param); + handle_connect_state_connected(event, (esp_a2d_cb_param_t*)param); break; } case ESP_A2D_AUDIO_STATE_EVT: { - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT)); - a2d = (esp_a2d_cb_param_t *)(param); - if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { - s_pkt_cnt = 0; - } + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_STATE_EVT)); + a2d = (esp_a2d_cb_param_t*)(param); + if(ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { s_pkt_cnt = 0; } break; } case ESP_A2D_AUDIO_CFG_EVT: // not suppposed to occur for A2DP source - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT)); + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_CFG_EVT)); break; - case ESP_A2D_MEDIA_CTRL_ACK_EVT:{ - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); - bt_app_av_media_proc(event, param); - break; - } + case ESP_A2D_MEDIA_CTRL_ACK_EVT: { + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); + bt_app_av_media_proc(event, param); + break; + } case BT_APP_HEART_BEAT_EVT: { - ESP_LOGV(TAG,QUOTE(BT_APP_HEART_BEAT_EVT)); + ESP_LOGV(TAG, QUOTE(BT_APP_HEART_BEAT_EVT)); bt_app_av_media_proc(event, param); break; } default: - ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event); + ESP_LOGE(TAG, "%s unhandled evt %d", __func__, event); break; } } -static void bt_app_av_state_disconnecting(uint16_t event, void *param) -{ - switch (event) { - case ESP_A2D_CONNECTION_STATE_EVT: - handle_connect_state_disconnecting( event, (esp_a2d_cb_param_t *)param); - break; - case ESP_A2D_AUDIO_STATE_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT)); - break; - case ESP_A2D_AUDIO_CFG_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT)); - break; - case ESP_A2D_MEDIA_CTRL_ACK_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); - break; - case BT_APP_HEART_BEAT_EVT: - ESP_LOG_DEBUG_EVENT(TAG,QUOTE(BT_APP_HEART_BEAT_EVT)); - break; - default: - ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event); - break; - } +static void bt_app_av_state_disconnecting(uint16_t event, void* param) { + switch(event) { + case ESP_A2D_CONNECTION_STATE_EVT: + handle_connect_state_disconnecting(event, (esp_a2d_cb_param_t*)param); + break; + case ESP_A2D_AUDIO_STATE_EVT: + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_STATE_EVT)); + break; + case ESP_A2D_AUDIO_CFG_EVT: + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_AUDIO_CFG_EVT)); + break; + case ESP_A2D_MEDIA_CTRL_ACK_EVT: + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT)); + break; + case BT_APP_HEART_BEAT_EVT: + ESP_LOG_DEBUG_EVENT(TAG, QUOTE(BT_APP_HEART_BEAT_EVT)); + break; + default: + ESP_LOGE(TAG, "%s unhandled evt %d", __func__, event); + break; + } } -static void bt_av_volume_changed(void) -{ - if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, - ESP_AVRC_RN_VOLUME_CHANGE)) { +static void bt_av_volume_changed(void) { + if(esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, ESP_AVRC_RN_VOLUME_CHANGE)) { esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_VOLUME_CHANGE, ESP_AVRC_RN_VOLUME_CHANGE, 0); } } -static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter) -{ - switch (event_id) { +static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t* event_parameter) { + switch(event_id) { case ESP_AVRC_RN_VOLUME_CHANGE: ESP_LOGI(BT_RC_CT_TAG, "Volume changed: %d", event_parameter->volume); ESP_LOGI(BT_RC_CT_TAG, "Set absolute volume: volume %d", event_parameter->volume + 5); @@ -970,17 +894,16 @@ static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *even break; } } -static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) -{ +static void bt_av_hdl_avrc_ct_evt(uint16_t event, void* p_param) { ESP_LOGD(BT_RC_CT_TAG, "%s evt %d", __func__, event); - esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param); - switch (event) { + esp_avrc_ct_cb_param_t* rc = (esp_avrc_ct_cb_param_t*)(p_param); + switch(event) { case ESP_AVRC_CT_CONNECTION_STATE_EVT: { - uint8_t *bda = rc->conn_stat.remote_bda; - ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", - rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + uint8_t* bda = rc->conn_stat.remote_bda; + ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", rc->conn_stat.connected, bda[0], bda[1], bda[2], + bda[3], bda[4], bda[5]); - if (rc->conn_stat.connected) { + if(rc->conn_stat.connected) { // get remote supported event_ids of peer AVRCP Target esp_avrc_ct_send_get_rn_capabilities_cmd(APP_RC_CT_TL_GET_CAPS); } else { @@ -1008,8 +931,7 @@ static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) break; } case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, - rc->get_rn_caps_rsp.evt_set.bits); + ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count, rc->get_rn_caps_rsp.evt_set.bits); s_avrc_peer_rn_cap.bits = rc->get_rn_caps_rsp.evt_set.bits; bt_av_volume_changed(); diff --git a/components/led_strip/led_strip.c b/components/led_strip/led_strip.c index 89f9f466..3fa72965 100644 --- a/components/led_strip/led_strip.c +++ b/components/led_strip/led_strip.c @@ -21,10 +21,10 @@ #include -#define LED_STRIP_TASK_SIZE (1024) -#define LED_STRIP_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define LED_STRIP_TASK_SIZE (1024) +#define LED_STRIP_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#define LED_STRIP_REFRESH_PERIOD_MS (30U) // TODO: add as parameter to led_strip_init +#define LED_STRIP_REFRESH_PERIOD_MS (30U) // TODO: add as parameter to led_strip_init #define LED_STRIP_NUM_RMT_ITEMS_PER_LED (24U) // Assumes 24 bit color for each led @@ -35,54 +35,50 @@ WS2812 Timing ****************************/ #define LED_STRIP_RMT_TICKS_BIT_1_HIGH_WS2812 9 // 900ns (900ns +/- 150ns per datasheet) -#define LED_STRIP_RMT_TICKS_BIT_1_LOW_WS2812 3 // 300ns (350ns +/- 150ns per datasheet) +#define LED_STRIP_RMT_TICKS_BIT_1_LOW_WS2812 3 // 300ns (350ns +/- 150ns per datasheet) #define LED_STRIP_RMT_TICKS_BIT_0_HIGH_WS2812 3 // 300ns (350ns +/- 150ns per datasheet) -#define LED_STRIP_RMT_TICKS_BIT_0_LOW_WS2812 9 // 900ns (900ns +/- 150ns per datasheet) +#define LED_STRIP_RMT_TICKS_BIT_0_LOW_WS2812 9 // 900ns (900ns +/- 150ns per datasheet) /**************************** SK6812 Timing ****************************/ #define LED_STRIP_RMT_TICKS_BIT_1_HIGH_SK6812 6 -#define LED_STRIP_RMT_TICKS_BIT_1_LOW_SK6812 6 +#define LED_STRIP_RMT_TICKS_BIT_1_LOW_SK6812 6 #define LED_STRIP_RMT_TICKS_BIT_0_HIGH_SK6812 3 -#define LED_STRIP_RMT_TICKS_BIT_0_LOW_SK6812 9 +#define LED_STRIP_RMT_TICKS_BIT_0_LOW_SK6812 9 /**************************** APA106 Timing ****************************/ #define LED_STRIP_RMT_TICKS_BIT_1_HIGH_APA106 14 // 1.36us +/- 150ns per datasheet -#define LED_STRIP_RMT_TICKS_BIT_1_LOW_APA106 3 // 350ns +/- 150ns per datasheet -#define LED_STRIP_RMT_TICKS_BIT_0_HIGH_APA106 3 // 350ns +/- 150ns per datasheet -#define LED_STRIP_RMT_TICKS_BIT_0_LOW_APA106 14 // 1.36us +/- 150ns per datasheet +#define LED_STRIP_RMT_TICKS_BIT_1_LOW_APA106 3 // 350ns +/- 150ns per datasheet +#define LED_STRIP_RMT_TICKS_BIT_0_HIGH_APA106 3 // 350ns +/- 150ns per datasheet +#define LED_STRIP_RMT_TICKS_BIT_0_LOW_APA106 14 // 1.36us +/- 150ns per datasheet // Function pointer for generating waveforms based on different LED drivers -typedef void (*led_fill_rmt_items_fn)(struct led_color_t *led_strip_buf, rmt_item32_t *rmt_items, uint32_t led_strip_length); +typedef void (*led_fill_rmt_items_fn)(struct led_color_t* led_strip_buf, rmt_item32_t* rmt_items, uint32_t led_strip_length); -static inline void led_strip_fill_item_level(rmt_item32_t* item, int high_ticks, int low_ticks) -{ +static inline void led_strip_fill_item_level(rmt_item32_t* item, int high_ticks, int low_ticks) { item->level0 = 1; item->duration0 = high_ticks; item->level1 = 0; item->duration1 = low_ticks; } -static inline void led_strip_rmt_bit_1_sk6812(rmt_item32_t* item) -{ +static inline void led_strip_rmt_bit_1_sk6812(rmt_item32_t* item) { led_strip_fill_item_level(item, LED_STRIP_RMT_TICKS_BIT_1_HIGH_SK6812, LED_STRIP_RMT_TICKS_BIT_1_LOW_SK6812); } -static inline void led_strip_rmt_bit_0_sk6812(rmt_item32_t* item) -{ +static inline void led_strip_rmt_bit_0_sk6812(rmt_item32_t* item) { led_strip_fill_item_level(item, LED_STRIP_RMT_TICKS_BIT_0_HIGH_SK6812, LED_STRIP_RMT_TICKS_BIT_0_LOW_SK6812); } -static void led_strip_fill_rmt_items_sk6812(struct led_color_t *led_strip_buf, rmt_item32_t *rmt_items, uint32_t led_strip_length) -{ +static void led_strip_fill_rmt_items_sk6812(struct led_color_t* led_strip_buf, rmt_item32_t* rmt_items, uint32_t led_strip_length) { uint32_t rmt_items_index = 0; - for (uint32_t led_index = 0; led_index < led_strip_length; led_index++) { + for(uint32_t led_index = 0; led_index < led_strip_length; led_index++) { struct led_color_t led_color = led_strip_buf[led_index]; - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.green >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_sk6812(&(rmt_items[rmt_items_index])); @@ -91,7 +87,7 @@ static void led_strip_fill_rmt_items_sk6812(struct led_color_t *led_strip_buf, r } rmt_items_index++; } - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.red >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_sk6812(&(rmt_items[rmt_items_index])); @@ -100,7 +96,7 @@ static void led_strip_fill_rmt_items_sk6812(struct led_color_t *led_strip_buf, r } rmt_items_index++; } - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.blue >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_sk6812(&(rmt_items[rmt_items_index])); @@ -112,23 +108,20 @@ static void led_strip_fill_rmt_items_sk6812(struct led_color_t *led_strip_buf, r } } -static inline void led_strip_rmt_bit_1_ws2812(rmt_item32_t* item) -{ +static inline void led_strip_rmt_bit_1_ws2812(rmt_item32_t* item) { led_strip_fill_item_level(item, LED_STRIP_RMT_TICKS_BIT_1_HIGH_WS2812, LED_STRIP_RMT_TICKS_BIT_1_LOW_WS2812); } -static inline void led_strip_rmt_bit_0_ws2812(rmt_item32_t* item) -{ +static inline void led_strip_rmt_bit_0_ws2812(rmt_item32_t* item) { led_strip_fill_item_level(item, LED_STRIP_RMT_TICKS_BIT_0_HIGH_WS2812, LED_STRIP_RMT_TICKS_BIT_0_LOW_WS2812); } -static void led_strip_fill_rmt_items_ws2812(struct led_color_t *led_strip_buf, rmt_item32_t *rmt_items, uint32_t led_strip_length) -{ +static void led_strip_fill_rmt_items_ws2812(struct led_color_t* led_strip_buf, rmt_item32_t* rmt_items, uint32_t led_strip_length) { uint32_t rmt_items_index = 0; - for (uint32_t led_index = 0; led_index < led_strip_length; led_index++) { + for(uint32_t led_index = 0; led_index < led_strip_length; led_index++) { struct led_color_t led_color = led_strip_buf[led_index]; - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.green >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_ws2812(&(rmt_items[rmt_items_index])); @@ -137,7 +130,7 @@ static void led_strip_fill_rmt_items_ws2812(struct led_color_t *led_strip_buf, r } rmt_items_index++; } - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.red >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_ws2812(&(rmt_items[rmt_items_index])); @@ -146,7 +139,7 @@ static void led_strip_fill_rmt_items_ws2812(struct led_color_t *led_strip_buf, r } rmt_items_index++; } - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.blue >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_ws2812(&(rmt_items[rmt_items_index])); @@ -158,23 +151,20 @@ static void led_strip_fill_rmt_items_ws2812(struct led_color_t *led_strip_buf, r } } -static inline void led_strip_rmt_bit_1_apa106(rmt_item32_t* item) -{ +static inline void led_strip_rmt_bit_1_apa106(rmt_item32_t* item) { led_strip_fill_item_level(item, LED_STRIP_RMT_TICKS_BIT_1_HIGH_APA106, LED_STRIP_RMT_TICKS_BIT_1_LOW_APA106); } -static inline void led_strip_rmt_bit_0_apa106(rmt_item32_t* item) -{ +static inline void led_strip_rmt_bit_0_apa106(rmt_item32_t* item) { led_strip_fill_item_level(item, LED_STRIP_RMT_TICKS_BIT_0_HIGH_APA106, LED_STRIP_RMT_TICKS_BIT_0_LOW_APA106); } -static void led_strip_fill_rmt_items_apa106(struct led_color_t *led_strip_buf, rmt_item32_t *rmt_items, uint32_t led_strip_length) -{ +static void led_strip_fill_rmt_items_apa106(struct led_color_t* led_strip_buf, rmt_item32_t* rmt_items, uint32_t led_strip_length) { uint32_t rmt_items_index = 0; - for (uint32_t led_index = 0; led_index < led_strip_length; led_index++) { + for(uint32_t led_index = 0; led_index < led_strip_length; led_index++) { struct led_color_t led_color = led_strip_buf[led_index]; - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.red >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_apa106(&(rmt_items[rmt_items_index])); @@ -183,7 +173,7 @@ static void led_strip_fill_rmt_items_apa106(struct led_color_t *led_strip_buf, r } rmt_items_index++; } - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.green >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_apa106(&(rmt_items[rmt_items_index])); @@ -192,7 +182,7 @@ static void led_strip_fill_rmt_items_apa106(struct led_color_t *led_strip_buf, r } rmt_items_index++; } - for (uint8_t bit = 8; bit != 0; bit--) { + for(uint8_t bit = 8; bit != 0; bit--) { uint8_t bit_set = (led_color.blue >> (bit - 1)) & 1; if(bit_set) { led_strip_rmt_bit_1_apa106(&(rmt_items[rmt_items_index])); @@ -204,34 +194,31 @@ static void led_strip_fill_rmt_items_apa106(struct led_color_t *led_strip_buf, r } } -static void led_strip_task(void *arg) -{ - struct led_strip_t *led_strip = (struct led_strip_t *)arg; +static void led_strip_task(void* arg) { + struct led_strip_t* led_strip = (struct led_strip_t*)arg; led_fill_rmt_items_fn led_make_waveform = NULL; size_t num_items_malloc = (LED_STRIP_NUM_RMT_ITEMS_PER_LED * led_strip->led_strip_length); - rmt_item32_t *rmt_items = (rmt_item32_t*) malloc(sizeof(rmt_item32_t) * num_items_malloc); - if (!rmt_items) { - vTaskDelete(NULL); - } + rmt_item32_t* rmt_items = (rmt_item32_t*)malloc(sizeof(rmt_item32_t) * num_items_malloc); + if(!rmt_items) { vTaskDelete(NULL); } - switch (led_strip->rgb_led_type) { - case RGB_LED_TYPE_WS2812: - led_make_waveform = led_strip_fill_rmt_items_ws2812; - break; + switch(led_strip->rgb_led_type) { + case RGB_LED_TYPE_WS2812: + led_make_waveform = led_strip_fill_rmt_items_ws2812; + break; - case RGB_LED_TYPE_SK6812: - led_make_waveform = led_strip_fill_rmt_items_sk6812; - break; + case RGB_LED_TYPE_SK6812: + led_make_waveform = led_strip_fill_rmt_items_sk6812; + break; - case RGB_LED_TYPE_APA106: - led_make_waveform = led_strip_fill_rmt_items_apa106; - break; + case RGB_LED_TYPE_APA106: + led_make_waveform = led_strip_fill_rmt_items_apa106; + break; - default: - // Will avoid keeping it point to NULL - led_make_waveform = led_strip_fill_rmt_items_ws2812; - break; + default: + // Will avoid keeping it point to NULL + led_make_waveform = led_strip_fill_rmt_items_ws2812; + break; }; for(;;) { @@ -240,25 +227,16 @@ static void led_strip_task(void *arg) xSemaphoreTake(led_strip->access_semaphore, portMAX_DELAY); - led_make_waveform(led_strip->led_strip_working, - rmt_items, - led_strip->led_strip_length); - rmt_write_items(led_strip->rmt_channel, - rmt_items, - num_items_malloc, - false); + led_make_waveform(led_strip->led_strip_working, rmt_items, led_strip->led_strip_length); + rmt_write_items(led_strip->rmt_channel, rmt_items, num_items_malloc, false); } - if (rmt_items) { - free(rmt_items); - } + if(rmt_items) { free(rmt_items); } vTaskDelete(NULL); } -static bool led_strip_init_rmt(struct led_strip_t *led_strip) -{ - rmt_config_t rmt_cfg = { - .rmt_mode = RMT_MODE_TX, +static bool led_strip_init_rmt(struct led_strip_t* led_strip) { + rmt_config_t rmt_cfg = {.rmt_mode = RMT_MODE_TX, .channel = led_strip->rmt_channel, .clk_div = LED_STRIP_RMT_CLK_DIV, .gpio_num = led_strip->gpio, @@ -271,99 +249,69 @@ static bool led_strip_init_rmt(struct led_strip_t *led_strip) .carrier_en = false, .idle_level = RMT_IDLE_LEVEL_LOW, .idle_output_en = true, - } - }; + }}; esp_err_t cfg_ok = rmt_config(&rmt_cfg); - if (cfg_ok != ESP_OK) { - return false; - } + if(cfg_ok != ESP_OK) { return false; } esp_err_t install_ok = rmt_driver_install(rmt_cfg.channel, 0, 0); - if (install_ok != ESP_OK) { - return false; - } + if(install_ok != ESP_OK) { return false; } return true; } -bool led_strip_init(struct led_strip_t *led_strip) -{ +bool led_strip_init(struct led_strip_t* led_strip) { static EXT_RAM_ATTR TaskHandle_t task_created; - StaticTask_t* xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - static EXT_RAM_ATTR StackType_t xStack[LED_STRIP_TASK_SIZE] __attribute__ ((aligned (4))); + StaticTask_t* xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + static EXT_RAM_ATTR StackType_t xStack[LED_STRIP_TASK_SIZE] __attribute__((aligned(4))); - if ((led_strip == NULL) || - (led_strip->rmt_channel >= RMT_CHANNEL_MAX) || - (led_strip->gpio > GPIO_NUM_33) || - (led_strip->led_strip_working == NULL) || - (led_strip->led_strip_showing == NULL) || - (led_strip->led_strip_length == 0) || + if((led_strip == NULL) || (led_strip->rmt_channel >= RMT_CHANNEL_MAX) || (led_strip->gpio > GPIO_NUM_33) || + (led_strip->led_strip_working == NULL) || (led_strip->led_strip_showing == NULL) || (led_strip->led_strip_length == 0) || (led_strip->access_semaphore == NULL)) { return false; } - if(led_strip->led_strip_working == led_strip->led_strip_showing) { - return false; - } + if(led_strip->led_strip_working == led_strip->led_strip_showing) { return false; } memset(led_strip->led_strip_working, 0, sizeof(struct led_color_t) * led_strip->led_strip_length); memset(led_strip->led_strip_showing, 0, sizeof(struct led_color_t) * led_strip->led_strip_length); bool init_rmt = led_strip_init_rmt(led_strip); - if (!init_rmt) { - return false; - } + if(!init_rmt) { return false; } xSemaphoreGive(led_strip->access_semaphore); - task_created = xTaskCreateStatic(led_strip_task, - "led_strip_task", - LED_STRIP_TASK_SIZE, - led_strip, - LED_STRIP_TASK_PRIORITY, - xStack, xTaskBuffer); + task_created = xTaskCreateStatic(led_strip_task, "led_strip_task", LED_STRIP_TASK_SIZE, led_strip, LED_STRIP_TASK_PRIORITY, xStack, xTaskBuffer); - if (!task_created) { - return false; - } + if(!task_created) { return false; } return true; } -bool led_strip_set_pixel_color(struct led_strip_t *led_strip, uint32_t pixel_num, struct led_color_t *color) -{ +bool led_strip_set_pixel_color(struct led_strip_t* led_strip, uint32_t pixel_num, struct led_color_t* color) { bool set_led_success = true; - if ((!led_strip) || (!color) || (pixel_num > led_strip->led_strip_length)) { - return false; - } + if((!led_strip) || (!color) || (pixel_num > led_strip->led_strip_length)) { return false; } led_strip->led_strip_working[pixel_num] = *color; return set_led_success; } -bool led_strip_set_pixel_rgb(struct led_strip_t *led_strip, uint32_t pixel_num, uint8_t red, uint8_t green, uint8_t blue) -{ +bool led_strip_set_pixel_rgb(struct led_strip_t* led_strip, uint32_t pixel_num, uint8_t red, uint8_t green, uint8_t blue) { bool set_led_success = true; - if ((!led_strip) || (pixel_num > led_strip->led_strip_length)) { - return false; - } + if((!led_strip) || (pixel_num > led_strip->led_strip_length)) { return false; } - led_strip->led_strip_working[pixel_num].red = red; + led_strip->led_strip_working[pixel_num].red = red; led_strip->led_strip_working[pixel_num].green = green; - led_strip->led_strip_working[pixel_num].blue = blue; + led_strip->led_strip_working[pixel_num].blue = blue; return set_led_success; } -bool led_strip_get_pixel_color(struct led_strip_t *led_strip, uint32_t pixel_num, struct led_color_t *color) -{ +bool led_strip_get_pixel_color(struct led_strip_t* led_strip, uint32_t pixel_num, struct led_color_t* color) { bool get_success = true; - if ((!led_strip) || - (pixel_num > led_strip->led_strip_length) || - (!color)) { + if((!led_strip) || (pixel_num > led_strip->led_strip_length) || (!color)) { color = NULL; return false; } @@ -376,15 +324,12 @@ bool led_strip_get_pixel_color(struct led_strip_t *led_strip, uint32_t pixel_num /** * Updates the led buffer to be shown */ -bool led_strip_show(struct led_strip_t *led_strip) -{ +bool led_strip_show(struct led_strip_t* led_strip) { bool success = true; - if (!led_strip) { - return false; - } + if(!led_strip) { return false; } /* copy the current buffer for display */ - memcpy(led_strip->led_strip_showing,led_strip->led_strip_working, sizeof(struct led_color_t) * led_strip->led_strip_length); + memcpy(led_strip->led_strip_showing, led_strip->led_strip_working, sizeof(struct led_color_t) * led_strip->led_strip_length); xSemaphoreGive(led_strip->access_semaphore); @@ -394,16 +339,11 @@ bool led_strip_show(struct led_strip_t *led_strip) /** * Clears the LED strip */ -bool led_strip_clear(struct led_strip_t *led_strip) -{ +bool led_strip_clear(struct led_strip_t* led_strip) { bool success = true; - if (!led_strip) { - return false; - } + if(!led_strip) { return false; } - memset(led_strip->led_strip_working, - 0, - sizeof(struct led_color_t) * led_strip->led_strip_length); + memset(led_strip->led_strip_working, 0, sizeof(struct led_color_t) * led_strip->led_strip_length); return success; } diff --git a/components/led_strip/led_strip.h b/components/led_strip/led_strip.h index 3051c1ca..ea00e789 100644 --- a/components/led_strip/led_strip.h +++ b/components/led_strip/led_strip.h @@ -43,22 +43,22 @@ struct led_strip_t { // RMT peripheral settings rmt_channel_t rmt_channel; - + gpio_num_t gpio; // Must be less than GPIO_NUM_33 - struct led_color_t *led_strip_working; - struct led_color_t *led_strip_showing; + struct led_color_t* led_strip_working; + struct led_color_t* led_strip_showing; SemaphoreHandle_t access_semaphore; }; -bool led_strip_init(struct led_strip_t *led_strip); +bool led_strip_init(struct led_strip_t* led_strip); /** * Sets the pixel at pixel_num to color. */ -bool led_strip_set_pixel_color(struct led_strip_t *led_strip, uint32_t pixel_num, struct led_color_t *color); -bool led_strip_set_pixel_rgb(struct led_strip_t *led_strip, uint32_t pixel_num, uint8_t red, uint8_t green, uint8_t blue); +bool led_strip_set_pixel_color(struct led_strip_t* led_strip, uint32_t pixel_num, struct led_color_t* color); +bool led_strip_set_pixel_rgb(struct led_strip_t* led_strip, uint32_t pixel_num, uint8_t red, uint8_t green, uint8_t blue); /** * Get the pixel color at pixel_num for the led strip that is currently being shown! * NOTE: If you call set_pixel_color then get_pixel_color for the same pixel_num, you will not @@ -67,17 +67,17 @@ bool led_strip_set_pixel_rgb(struct led_strip_t *led_strip, uint32_t pixel_num, * * If there is an invalid argument, color will point to NULL and this function will return false. */ -bool led_strip_get_pixel_color(struct led_strip_t *led_strip, uint32_t pixel_num, struct led_color_t *color); +bool led_strip_get_pixel_color(struct led_strip_t* led_strip, uint32_t pixel_num, struct led_color_t* color); /** * Updates the led buffer to be shown using double buffering. */ -bool led_strip_show(struct led_strip_t *led_strip); +bool led_strip_show(struct led_strip_t* led_strip); /** * Clears the LED strip. */ -bool led_strip_clear(struct led_strip_t *led_strip); +bool led_strip_clear(struct led_strip_t* led_strip); #ifdef __cplusplus } diff --git a/components/led_strip/led_vu.c b/components/led_strip/led_vu.c index f62b596b..a4258598 100644 --- a/components/led_strip/led_vu.c +++ b/components/led_strip/led_vu.c @@ -27,13 +27,13 @@ #include "accessors.h" #include "led_vu.h" -static const char *TAG = "led_vu"; +static const char* TAG = "led_vu"; static void (*battery_handler_chain)(float value, int cells); static void battery_svc(float value, int cells); static int battery_status = 0; -#define LED_VU_STACK_SIZE (3*1024) +#define LED_VU_STACK_SIZE (3 * 1024) #define LED_VU_PEAK_HOLD 6U @@ -44,10 +44,10 @@ static int battery_status = 0; #define LED_VU_STATUS_GREEN 75 #define LED_VU_STATUS_RED 25 -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) struct led_strip_t* led_display = NULL; -static EXT_RAM_ATTR struct led_strip_t led_strip_config; +static EXT_RAM_ATTR struct led_strip_t led_strip_config; static EXT_RAM_ATTR struct { int gpio; @@ -58,41 +58,40 @@ static EXT_RAM_ATTR struct { int vu_status; } strip; -static int led_addr(int pos ) { - if (pos < 0) return pos + strip.length; - if (pos >= strip.length) return pos - strip.length; +static int led_addr(int pos) { + if(pos < 0) return pos + strip.length; + if(pos >= strip.length) return pos - strip.length; return pos; } static void battery_svc(float value, int cells) { - battery_status = battery_level_svc(); - ESP_LOGI(TAG, "Called for battery service with volt:%f cells:%d status:%d", value, cells, battery_status); + battery_status = battery_level_svc(); + ESP_LOGI(TAG, "Called for battery service with volt:%f cells:%d status:%d", value, cells, battery_status); - if (battery_handler_chain) battery_handler_chain(value, cells); + if(battery_handler_chain) battery_handler_chain(value, cells); } /**************************************************************************************** * Initialize the led vu strip if configured. * */ -void led_vu_init() -{ - sys_dev_led_strip*config; - if(!SYS_DEV_LEDSTRIP(config)){ - ESP_LOGI(TAG,"No LED Strip configuration"); +void led_vu_init() { + sys_dev_led_strip* config; + if(!SYS_DEV_LEDSTRIP(config)) { + ESP_LOGI(TAG, "No LED Strip configuration"); return; } - if(config->gpio<0){ - ESP_LOGI(TAG,"LED Strip has no GPIO configured"); + if(config->gpio < 0) { + ESP_LOGI(TAG, "LED Strip has no GPIO configured"); return; } - ESP_LOGI(TAG, "Initializing led_vu"); - // Initialize led VU strip + ESP_LOGI(TAG, "Initializing led_vu"); + // Initialize led VU strip strip.length = config->length; strip.gpio = config->gpio; - + // check for valid configuration - if (config->strip_type == sys_dev_strip_types_LS_UNKNOWN || config->gpio <0) { + if(config->strip_type == sys_dev_strip_types_LS_UNKNOWN || config->gpio < 0) { ESP_LOGI(TAG, "led_vu configuration invalid"); return; } @@ -100,25 +99,25 @@ void led_vu_init() battery_handler_chain = battery_handler_svc; battery_handler_svc = battery_svc; battery_status = battery_level_svc(); - - if (strip.length > LED_VU_MAX_LENGTH) strip.length = LED_VU_MAX_LENGTH; + + if(strip.length > LED_VU_MAX_LENGTH) strip.length = LED_VU_MAX_LENGTH; // initialize vu meter settings - if (strip.length < 10) { + if(strip.length < 10) { // single bar for small strips strip.vu_length = strip.length; - strip.vu_start_l = 0; + strip.vu_start_l = 0; strip.vu_start_r = strip.vu_start_l; strip.vu_status = 0; } else { - strip.vu_length = (strip.length - 1) / 2; - strip.vu_start_l = (strip.length % 2) ? strip.vu_length -1 : strip.vu_length; + strip.vu_length = (strip.length - 1) / 2; + strip.vu_start_l = (strip.length % 2) ? strip.vu_length - 1 : strip.vu_length; strip.vu_start_r = strip.vu_length + 1; strip.vu_status = strip.vu_length; } ESP_LOGI(TAG, "vu meter using length:%d left:%d right:%d status:%d", strip.vu_length, strip.vu_start_l, strip.vu_start_r, strip.vu_status); // create driver configuration - led_strip_config.rgb_led_type = config->strip_type == sys_dev_strip_types_LS_WS2812?RGB_LED_TYPE_WS2812:RGB_LED_TYPE_MAX; + led_strip_config.rgb_led_type = config->strip_type == sys_dev_strip_types_LS_WS2812 ? RGB_LED_TYPE_WS2812 : RGB_LED_TYPE_MAX; led_strip_config.access_semaphore = xSemaphoreCreateBinary(); led_strip_config.led_strip_length = strip.length; led_strip_config.led_strip_working = heap_caps_malloc(strip.length * sizeof(struct led_color_t), MALLOC_CAP_8BIT); @@ -126,9 +125,9 @@ void led_vu_init() led_strip_config.gpio = strip.gpio; led_strip_config.rmt_channel = RMT_NEXT_TX_CHANNEL(); - // initialize driver + // initialize driver bool led_init_ok = led_strip_init(&led_strip_config); - if (led_init_ok) { + if(led_init_ok) { led_display = &led_strip_config; ESP_LOGI(TAG, "led_vu using gpio:%d length:%d on channel:%d", strip.gpio, strip.length, led_strip_config.rmt_channel); } else { @@ -140,18 +139,15 @@ void led_vu_init() rmt_set_mem_block_num(led_strip_config.rmt_channel, 7); led_vu_clear(led_display); - - } - -inline bool inRange(double x, double y, double z) { - return (x > y && x < z); } +inline bool inRange(double x, double y, double z) { return (x > y && x < z); } + /**************************************************************************************** * Returns the led strip length */ uint16_t led_vu_string_length() { - if (!led_display) return 0; + if(!led_display) return 0; return (uint16_t)strip.length; } @@ -159,7 +155,7 @@ uint16_t led_vu_string_length() { * Turns all LEDs off (Black) */ void led_vu_clear() { - if (!led_display) return; + if(!led_display) return; led_strip_clear(led_display); led_strip_show(led_display); @@ -171,13 +167,11 @@ void led_vu_clear() { * note - all colors are adjusted for brightness */ void led_vu_color_all(uint8_t r, uint8_t g, uint8_t b) { - if (!led_display) return; + if(!led_display) return; - struct led_color_t color_on = {.red = r, .green = g, .blue = b}; + struct led_color_t color_on = {.red = r, .green = g, .blue = b}; - for (int i = 0 ; i < strip.length ; i ++){ - led_strip_set_pixel_color(led_display, i, &color_on); - } + for(int i = 0; i < strip.length; i++) { led_strip_set_pixel_color(led_display, i, &color_on); } led_strip_show(led_display); } @@ -189,13 +183,13 @@ void led_vu_color_all(uint8_t r, uint8_t g, uint8_t b) { * data - array of rgb values in multiples of 3 bytes */ void led_vu_data(uint8_t* data, uint16_t offset, uint16_t length) { - if (!led_display) return; + if(!led_display) return; - uint8_t* p = (uint8_t*) data; - for (int i = 0; i < length; i++) { - led_strip_set_pixel_rgb(led_display, i+offset, *p, *(p+1), *(p+2)); - p+=3; - } + uint8_t* p = (uint8_t*)data; + for(int i = 0; i < length; i++) { + led_strip_set_pixel_rgb(led_display, i + offset, *p, *(p + 1), *(p + 2)); + p += 3; + } led_strip_show(led_display); } @@ -207,50 +201,48 @@ void led_vu_data(uint8_t* data, uint16_t offset, uint16_t length) { * length - size of array */ void led_vu_spectrum(uint8_t* data, int bright, int length, int style) { - if (!led_display) return; - uint8_t gain,r,g,b; + if(!led_display) return; + uint8_t gain, r, g, b; int width = strip.length / length; int pos = 0; - uint8_t* p = (uint8_t*) data; - for (int i=0; i LED_VU_MAX-step) ? LED_VU_MAX : g + step; + if(r == 0 && g == 0 && b == 0) { + r = LED_VU_MAX; + g = step; + } else if(b == 0) { + g = (g > LED_VU_MAX - step) ? LED_VU_MAX : g + step; r = (r < step) ? 0 : r - step; - if (r == 0) b = step; - } else if (r == 0) { - b = (b > LED_VU_MAX-step) ? LED_VU_MAX : b + step; - g = (g < step) ? 0 : g- step; - if (g == 0) r = step; - } else { - r = (r > LED_VU_MAX-step) ? LED_VU_MAX : r + step; + if(r == 0) b = step; + } else if(r == 0) { + b = (b > LED_VU_MAX - step) ? LED_VU_MAX : b + step; + g = (g < step) ? 0 : g - step; + if(g == 0) r = step; + } else { + r = (r > LED_VU_MAX - step) ? LED_VU_MAX : r + step; b = (b < step) ? 0 : b - step; - if (r == 0) b = step; + if(r == 0) b = step; } - uint8_t rp = r * gain / LED_VU_MAX; - uint8_t gp = g * gain / LED_VU_MAX; - uint8_t bp = b * gain / LED_VU_MAX; + uint8_t rp = r * gain / LED_VU_MAX; + uint8_t gp = g * gain / LED_VU_MAX; + uint8_t bp = b * gain / LED_VU_MAX; // set led color speed++; - if (comet) { + if(comet) { led_strip_clear(led_display); - led_strip_set_pixel_rgb(led_display, led_addr(led_pos-1), rp/2, gp/2, bp/2); - led_strip_set_pixel_rgb(led_display, led_addr(led_pos-2), rp/4, gp/4, bp/4); - led_strip_set_pixel_rgb(led_display, led_addr(led_pos-3), rp/8, gp/8, bp/8); + led_strip_set_pixel_rgb(led_display, led_addr(led_pos - 1), rp / 2, gp / 2, bp / 2); + led_strip_set_pixel_rgb(led_display, led_addr(led_pos - 2), rp / 4, gp / 4, bp / 4); + led_strip_set_pixel_rgb(led_display, led_addr(led_pos - 3), rp / 8, gp / 8, bp / 8); //led_strip_set_pixel_rgb(led_display, led_addr(led_pos-4), 0, 0, 0); } - for (int i = 0; i < speed; i++) { + for(int i = 0; i < speed; i++) { led_strip_set_pixel_rgb(led_display, led_pos, rp, gp, bp); led_pos = led_addr(++led_pos); } - + led_strip_show(led_display); } @@ -318,21 +310,21 @@ void led_vu_display(int vu_l, int vu_r, int bright, bool comet) { static int peak_r = 0; static int decay_l = 0; static int decay_r = 0; - if (!led_display) return; + if(!led_display) return; // single bar - if (strip.vu_start_l == strip.vu_start_r) { + if(strip.vu_start_l == strip.vu_start_r) { vu_r = (vu_l + vu_r) / 2; vu_l = 0; } // scale vu samples to length - vu_l = vu_l * strip.vu_length / bright; + vu_l = vu_l * strip.vu_length / bright; vu_r = vu_r * strip.vu_length / bright; // calculate hold peaks - if (peak_l > vu_l) { - if (decay_l-- < 0) { + if(peak_l > vu_l) { + if(decay_l-- < 0) { decay_l = LED_VU_PEAK_HOLD; peak_l--; } @@ -340,8 +332,8 @@ void led_vu_display(int vu_l, int vu_r, int bright, bool comet) { peak_l = vu_l; decay_l = LED_VU_PEAK_HOLD; } - if (peak_r > vu_r) { - if (decay_r-- < 0) { + if(peak_r > vu_r) { + if(decay_r-- < 0) { decay_r = LED_VU_PEAK_HOLD; peak_r--; } @@ -354,45 +346,44 @@ void led_vu_display(int vu_l, int vu_r, int bright, bool comet) { led_strip_clear(led_display); // set the led bar values - uint8_t step = bright / (strip.vu_length-1); - if (step < 1) step = 1; // dor low brightness or larger strips + uint8_t step = bright / (strip.vu_length - 1); + if(step < 1) step = 1; // dor low brightness or larger strips uint8_t g = bright * 2 / 3; // more red at top uint8_t r = 0; int shift = 0; - for (int i = 0; i < strip.vu_length; i++) { + for(int i = 0; i < strip.vu_length; i++) { // set left - if (i == peak_l) { + if(i == peak_l) { led_strip_set_pixel_rgb(led_display, strip.vu_start_l - i, r, g, bright); - } else if (i <= vu_l) { - shift = vu_l - i; - if (comet) - led_strip_set_pixel_rgb(led_display, strip.vu_start_l - i, r>>shift, g>>shift, 0); + } else if(i <= vu_l) { + shift = vu_l - i; + if(comet) + led_strip_set_pixel_rgb(led_display, strip.vu_start_l - i, r >> shift, g >> shift, 0); else led_strip_set_pixel_rgb(led_display, strip.vu_start_l - i, r, g, 0); } - // set right - if (i == peak_r) { + // set right + if(i == peak_r) { led_strip_set_pixel_rgb(led_display, strip.vu_start_r + i, r, g, bright); - } else if (i <= vu_r) { + } else if(i <= vu_r) { shift = vu_r - i; - if (comet) - led_strip_set_pixel_rgb(led_display, strip.vu_start_r + i, r>>shift, g>>shift, 0); + if(comet) + led_strip_set_pixel_rgb(led_display, strip.vu_start_r + i, r >> shift, g >> shift, 0); else led_strip_set_pixel_rgb(led_display, strip.vu_start_r + i, r, g, 0); } // adjust colors (with limit checks) - r = (r > bright-step) ? bright : r + step; + r = (r > bright - step) ? bright : r + step; g = (g < step) ? 0 : g - step; } // show battery status - if (battery_status > LED_VU_STATUS_GREEN) + if(battery_status > LED_VU_STATUS_GREEN) led_strip_set_pixel_rgb(led_display, strip.vu_status, 0, bright, 0); - else if (battery_status > LED_VU_STATUS_RED) - led_strip_set_pixel_rgb(led_display, strip.vu_status, bright/2, bright/2, 0); - else if (battery_status > 0) + else if(battery_status > LED_VU_STATUS_RED) + led_strip_set_pixel_rgb(led_display, strip.vu_status, bright / 2, bright / 2, 0); + else if(battery_status > 0) led_strip_set_pixel_rgb(led_display, strip.vu_status, bright, 0, 0); - + led_strip_show(led_display); } - diff --git a/components/led_strip/led_vu.h b/components/led_strip/led_vu.h index eedf3b38..ee206ffe 100644 --- a/components/led_strip/led_vu.h +++ b/components/led_strip/led_vu.h @@ -10,13 +10,13 @@ #include -#define LED_VU_MAX 255U -#define LED_VU_BRIGHT 20U +#define LED_VU_MAX 255U +#define LED_VU_BRIGHT 20U -#define led_vu_color_red(B) led_vu_color_all(B, 0, 0) -#define led_vu_color_green(B) led_vu_color_all(0, B, 0) -#define led_vu_color_blue(B) led_vu_color_all(0, 0, B) -#define led_vu_color_yellow(B) led_vu_color_all(B/2, B/2, 0) +#define led_vu_color_red(B) led_vu_color_all(B, 0, 0) +#define led_vu_color_green(B) led_vu_color_all(0, B, 0) +#define led_vu_color_blue(B) led_vu_color_all(0, 0, B) +#define led_vu_color_yellow(B) led_vu_color_all(B / 2, B / 2, 0) extern struct led_strip_t* led_display; @@ -28,4 +28,3 @@ void led_vu_spectrum(uint8_t* data, int bright, int length, int style); void led_vu_color_all(uint8_t r, uint8_t g, uint8_t b); void led_vu_data(uint8_t* data, uint16_t offset, uint16_t length); void led_vu_clear(); - diff --git a/components/metrics/Batch.cpp b/components/metrics/Batch.cpp index ebe37455..ab1d390e 100644 --- a/components/metrics/Batch.cpp +++ b/components/metrics/Batch.cpp @@ -28,20 +28,18 @@ namespace Metrics { Event& Batch::add_feature_event() { return add_event(feature_evt_name); } void Batch::add_remove_feature_event(const char* name, bool active) { - if (!active) { + if(!active) { remove_feature_event(name); } else { add_event(feature_evt_name).add_property(feature_flag_name, name); } } Event& Batch::add_feature_variant_event(const char* const name, const char* const value) { - return add_event(feature_evt_name) - .add_property(feature_flag_name, name) - .add_property(feature_flag_response_name, value); + return add_event(feature_evt_name).add_property(feature_flag_name, name).add_property(feature_flag_response_name, value); } void Batch::remove_feature_event(const char* name) { - for (Metrics::Event& e : _events) { - if (strcmp(e.get_name(), feature_evt_name) == 0) { + for(Metrics::Event& e : _events) { + if(strcmp(e.get_name(), feature_evt_name) == 0) { e.remove_property(feature_flag_name, name); return; } @@ -49,9 +47,7 @@ void Batch::remove_feature_event(const char* name) { } cJSON* Batch::to_json() { cJSON* batch_json = cJSON_CreateArray(); - for (Metrics::Event& e : _events) { - cJSON_AddItemToArray(batch_json, e.to_json(_metrics_uid.c_str())); - } + for(Metrics::Event& e : _events) { cJSON_AddItemToArray(batch_json, e.to_json(_metrics_uid.c_str())); } cJSON* message = cJSON_CreateObject(); cJSON_AddItemToObject(message, "batch", batch_json); cJSON_AddStringToObject(message, "api_key", _api_key); @@ -66,7 +62,7 @@ char* Batch::to_json_str() { void Batch::push() { int status_code = 0; - if (_metrics_uid.empty() && !_warned) { + if(_metrics_uid.empty() && !_warned) { ESP_LOGW(TAG, "Metrics disabled; no CID found"); _warned = true; return; @@ -78,9 +74,7 @@ void Batch::push() { status_code = metrics_http_post_request(json_str, _url); - if (status_code == 200 || status_code == 204) { - _events.clear(); - } + if(status_code == 200 || status_code == 204) { _events.clear(); } FREE_AND_NULL(json_str) ESP_LOGD(TAG, "Total duration for metrics call: %u. ", gettime_ms() - start_time); } @@ -89,32 +83,28 @@ void Batch::build_guid() { uint8_t raw[16]; std::ostringstream oss; esp_fill_random(raw, 16); - std::for_each(std::begin(raw), std::end(raw), [&oss](const uint8_t& byte) { - oss << std::hex << std::setw(2) << std::setfill('0') << static_cast(byte); - }); + std::for_each(std::begin(raw), std::end(raw), + [&oss](const uint8_t& byte) { oss << std::hex << std::setw(2) << std::setfill('0') << static_cast(byte); }); _metrics_uid = oss.str(); } void Batch::assign_id() { size_t size = 0; esp_err_t esp_err = ESP_OK; - _metrics_uid = std::string((char*)get_nvs_value_alloc_for_partition( - NVS_DEFAULT_PART_NAME, TAG, NVS_TYPE_BLOB, "cid", &size)); - if (_metrics_uid[0] == 'G') { + _metrics_uid = std::string((char*)get_nvs_value_alloc_for_partition(NVS_DEFAULT_PART_NAME, TAG, NVS_TYPE_BLOB, "cid", &size)); + if(_metrics_uid[0] == 'G') { ESP_LOGW(TAG, "Invalid ID. %s", _metrics_uid.c_str()); _metrics_uid.clear(); } - if (_metrics_uid.empty()) { + if(_metrics_uid.empty()) { build_guid(); - if (_metrics_uid.empty()) { + if(_metrics_uid.empty()) { ESP_LOGE(TAG, "ID Failed"); return; } ESP_LOGW(TAG, "Metrics ID: %s", _metrics_uid.c_str()); - esp_err = store_nvs_value_len_for_partition(NVS_DEFAULT_PART_NAME, TAG, NVS_TYPE_BLOB, - "cid", _metrics_uid.c_str(), _metrics_uid.length() + 1); - if (esp_err != ESP_OK) { - ESP_LOGE(TAG, "Store ID failed: %s", esp_err_to_name(esp_err)); - } + esp_err = + store_nvs_value_len_for_partition(NVS_DEFAULT_PART_NAME, TAG, NVS_TYPE_BLOB, "cid", _metrics_uid.c_str(), _metrics_uid.length() + 1); + if(esp_err != ESP_OK) { ESP_LOGE(TAG, "Store ID failed: %s", esp_err_to_name(esp_err)); } } } } // namespace Metrics diff --git a/components/metrics/Events.cpp b/components/metrics/Events.cpp index 7cb2c3b6..ebe1eb00 100644 --- a/components/metrics/Events.cpp +++ b/components/metrics/Events.cpp @@ -6,15 +6,15 @@ static const char* const TAG = "MetricsEvent"; namespace Metrics { Event& Event::add_property(const char* name, const char* value) { - ESP_LOGV(TAG, "Adding property %s:%s to event %s",name,value,_name); + ESP_LOGV(TAG, "Adding property %s:%s to event %s", name, value, _name); char* mutable_name = strdup_psram(name); // Cast away const-ness, be careful with this auto elem = properties.find(mutable_name); FREE_AND_NULL(mutable_name) - if (elem == properties.end()) { - ESP_LOGV(TAG, "Adding property %s:%s to event %s",name,value,_name); + if(elem == properties.end()) { + ESP_LOGV(TAG, "Adding property %s:%s to event %s", name, value, _name); properties.insert({strdup_psram(name), strdup_psram(value)}); } else { - ESP_LOGV(TAG, "Replacing value for property %s. Old: %s New: %s, Event: %s",name,elem->second,value,name); + ESP_LOGV(TAG, "Replacing value for property %s. Old: %s New: %s, Event: %s", name, elem->second, value, name); FREE_AND_NULL(elem->second) elem->second = strdup_psram(value); } @@ -22,27 +22,26 @@ Event& Event::add_property(const char* name, const char* value) { } bool Event::has_property_value(const char* name, const char* value) const { - ESP_LOGV(TAG, "Checking if event %s property %s has value %s",_name, name,value); - return std::any_of(properties.begin(), properties.end(), - [name, value](const std::pair& kv) { - ESP_LOGV(TAG, "Found property %s=%s", name,value); - return strcmp(kv.first, name) == 0 && strcmp(kv.second, value) == 0; - }); + ESP_LOGV(TAG, "Checking if event %s property %s has value %s", _name, name, value); + return std::any_of(properties.begin(), properties.end(), [name, value](const std::pair& kv) { + ESP_LOGV(TAG, "Found property %s=%s", name, value); + return strcmp(kv.first, name) == 0 && strcmp(kv.second, value) == 0; + }); } void Event::remove_property(const char* name, const char* value) { auto it = properties.begin(); - ESP_LOGV(TAG, "Removing event %s property %s=%s",_name, name,value); - while (it != properties.end()) { - if (strcmp(it->first, name) == 0 && strcmp(it->second, value)) { + ESP_LOGV(TAG, "Removing event %s property %s=%s", _name, name, value); + while(it != properties.end()) { + if(strcmp(it->first, name) == 0 && strcmp(it->second, value)) { properties.erase(it); return; } } - ESP_LOGV(TAG, "Property %s=%s not found.", name,value); + ESP_LOGV(TAG, "Property %s=%s not found.", name, value); } cJSON* Event::properties_to_json() { - ESP_LOGV(TAG, "Event %s properties to json.",_name); + ESP_LOGV(TAG, "Event %s properties to json.", _name); const esp_app_desc_t* desc = esp_ota_get_app_description(); #ifdef CONFIG_FW_PLATFORM_NAME const char* platform = CONFIG_FW_PLATFORM_NAME; @@ -52,7 +51,7 @@ cJSON* Event::properties_to_json() { cJSON* prop_json = cJSON_CreateObject(); auto it = properties.begin(); - while (it != properties.end()) { + while(it != properties.end()) { cJSON_AddStringToObject(prop_json, it->first, it->second); ++it; } @@ -71,7 +70,7 @@ cJSON* Event::to_json(const char* distinct_id) { // }, // "timestamp": "[optional timestamp in ISO 8601 format]" // } - ESP_LOGV(TAG,"Event %s to json",_name); + ESP_LOGV(TAG, "Event %s to json", _name); free_json(); _json = cJSON_CreateObject(); @@ -90,9 +89,7 @@ cJSON* Event::to_json(const char* distinct_id) { } void Event::free_json() { cJSON_Delete(_json); } void Event::update_time() { - if (_time == 0) { - _time = time(nullptr); - } + if(_time == 0) { _time = time(nullptr); } } } // namespace Metrics #endif \ No newline at end of file diff --git a/components/metrics/Events.h b/components/metrics/Events.h index f424d36b..7d4ce200 100644 --- a/components/metrics/Events.h +++ b/components/metrics/Events.h @@ -37,17 +37,18 @@ class Event { FREE_AND_NULL(_name); // Iterate through the map and free the elements - for (auto& kv : properties) { + for(auto& kv : properties) { free((void*)kv.first); free(kv.second); } properties.clear(); // Clear the map after freeing memory FREE_AND_NULL(_json); } + private: char* _name = nullptr; std::time_t _time; - cJSON* _json = nullptr; + cJSON* _json = nullptr; }; } // namespace Metrics diff --git a/components/metrics/Metrics.cpp b/components/metrics/Metrics.cpp index fe1b0d15..135da052 100644 --- a/components/metrics/Metrics.cpp +++ b/components/metrics/Metrics.cpp @@ -32,10 +32,10 @@ static const char* TAG = "metrics"; static bool metrics_usage_gen = false; static uint32_t metrics_usage_gen_time = 0; #ifndef METRICS_API_KEY - #pragma message "Metrics API key needs to be passed from the environment" - #define METRICS_API_KEY "ZZZ" +#pragma message "Metrics API key needs to be passed from the environment" +#define METRICS_API_KEY "ZZZ" #endif -static const char* metrics_api_key = METRICS_API_KEY; +static const char* metrics_api_key = METRICS_API_KEY; static const char* parms_str = "params"; static const char* properties_str = "properties"; static const char* user_properties_str = "user_properties"; @@ -47,15 +47,15 @@ extern cJSON* get_cmd_list(); Metrics::Batch batch; static void metrics_timer_cb(void* timer_id) { - if (batch.has_events()) { - if (!is_network_connected()) { + if(batch.has_events()) { + if(!is_network_connected()) { ESP_LOGV(TAG, "Network not connected. can't flush"); } else { ESP_LOGV(TAG, "Pushing events"); batch.push(); } } - if (gettime_ms() > metrics_usage_gen_time && !metrics_usage_gen) { + if(gettime_ms() > metrics_usage_gen_time && !metrics_usage_gen) { metrics_usage_gen = true; ESP_LOGV(TAG, "Generate command list to pull features"); cJSON* cmdlist = get_cmd_list(); @@ -66,7 +66,7 @@ static void metrics_timer_cb(void* timer_id) { void metrics_init() { ESP_LOGV(TAG, "Initializing metrics"); batch.configure(metrics_api_key, metrics_url); - if (!timer) { + if(!timer) { ESP_LOGE(TAG, "Metrics Timer failure"); } else { ESP_LOGV(TAG, "Starting timer"); @@ -113,21 +113,17 @@ void metrics_event(const char* name) { batch.add_event(name); } #else -static const char * not_enabled = " - (metrics not enabled, this is just marking where the call happens)"; -void metrics_init(){ +static const char* not_enabled = " - (metrics not enabled, this is just marking where the call happens)"; +void metrics_init() { #pragma message("Metrics disabled") - ESP_LOGD(TAG,"Metrics init%s",not_enabled); -} -void metrics_event_boot(const char* partition){ - ESP_LOGD(TAG,"Metrics Event Boot from partition %s%s",partition,not_enabled); -} -void metrics_event(const char* name){ - ESP_LOGD(TAG,"Metrics Event %s%s",name,not_enabled); + ESP_LOGD(TAG, "Metrics init%s", not_enabled); } +void metrics_event_boot(const char* partition) { ESP_LOGD(TAG, "Metrics Event Boot from partition %s%s", partition, not_enabled); } +void metrics_event(const char* name) { ESP_LOGD(TAG, "Metrics Event %s%s", name, not_enabled); } void metrics_add_feature(const char* name, bool active) { - ESP_LOGD(TAG,"Metrics add feature %s%s%s",name,active?"ACTIVE":"INACTIVE",not_enabled); + ESP_LOGD(TAG, "Metrics add feature %s%s%s", name, active ? "ACTIVE" : "INACTIVE", not_enabled); } -void metrics_add_feature_variant(const char* name, const char* format, ...){ +void metrics_add_feature_variant(const char* name, const char* format, ...) { va_list args; ESP_LOGV(TAG, "Feature %s", name); va_start(args, format); @@ -142,6 +138,6 @@ void metrics_add_feature_variant(const char* name, const char* format, ...){ vsnprintf(buffer.data(), buffer.size(), format, args); va_end(args); - ESP_LOGD(TAG,"Metrics add feature %s variant %s%s",name,buffer.data(),not_enabled); + ESP_LOGD(TAG, "Metrics add feature %s variant %s%s", name, buffer.data(), not_enabled); } #endif \ No newline at end of file diff --git a/components/metrics/http_handlers.c b/components/metrics/http_handlers.c index 05f75b3a..45ac4c45 100644 --- a/components/metrics/http_handlers.c +++ b/components/metrics/http_handlers.c @@ -15,23 +15,17 @@ typedef void (*HttpEventHandler)(esp_http_client_event_t* evt); static void handle_http_error(esp_http_client_event_t* evt) { ESP_LOGV(TAG, "ERROR"); } -static void handle_http_connected(esp_http_client_event_t* evt) { - ESP_LOGV(TAG, "ON_CONNECTED"); -} +static void handle_http_connected(esp_http_client_event_t* evt) { ESP_LOGV(TAG, "ON_CONNECTED"); } -static void handle_http_header_sent(esp_http_client_event_t* evt) { - ESP_LOGV(TAG, "HEADER_SENT"); -} +static void handle_http_header_sent(esp_http_client_event_t* evt) { ESP_LOGV(TAG, "HEADER_SENT"); } -static void handle_http_on_header(esp_http_client_event_t* evt) { - ESP_LOGV(TAG, "ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); -} +static void handle_http_on_header(esp_http_client_event_t* evt) { ESP_LOGV(TAG, "ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); } static void handle_http_on_data(esp_http_client_event_t* evt) { ESP_LOGV(TAG, "ON_DATA, len=%d", evt->data_len); ESP_LOGV(TAG, "ON_DATA, len=%d", evt->data_len); // Clean the buffer in case of a new request - if (output_len == 0 && evt->user_data) { + if(output_len == 0 && evt->user_data) { // we are just starting to copy the output data into the use ESP_LOGV(TAG, "Resetting buffer"); memset(evt->user_data, 0, MAX_HTTP_OUTPUT_BUFFER); @@ -44,44 +38,38 @@ static void handle_http_on_data(esp_http_client_event_t* evt) { // If user_data buffer is configured, copy the response into the buffer int copy_len = 0; - if (evt->user_data) { + if(evt->user_data) { ESP_LOGV(TAG, "Not Chunked response, with user data"); // The last byte in evt->user_data is kept for the NULL character in // case of out-of-bound access. copy_len = MIN(evt->data_len, (MAX_HTTP_OUTPUT_BUFFER - output_len)); - if (copy_len) { - memcpy(evt->user_data + output_len, evt->data, copy_len); - } + if(copy_len) { memcpy(evt->user_data + output_len, evt->data, copy_len); } } else { int content_len = esp_http_client_get_content_length(evt->client); - if (esp_http_client_is_chunked_response(evt->client)) { - esp_http_client_get_chunk_length(evt->client, &content_len); - } + if(esp_http_client_is_chunked_response(evt->client)) { esp_http_client_get_chunk_length(evt->client, &content_len); } - if (output_buffer == NULL) { + if(output_buffer == NULL) { // We initialize output_buffer with 0 because it is used by // strlen() and similar functions therefore should be null // terminated. - size_t len=(content_len + 1) * sizeof(char); - ESP_LOGV(TAG, "Init buffer %d",len); + size_t len = (content_len + 1) * sizeof(char); + ESP_LOGV(TAG, "Init buffer %d", len); output_buffer = (char*)malloc_init_external(len); output_len = 0; - if (output_buffer == NULL) { + if(output_buffer == NULL) { ESP_LOGE(TAG, "Buffer alloc failed."); return; } } copy_len = MIN(evt->data_len, (content_len - output_len)); - if (copy_len) { - memcpy(output_buffer + output_len, evt->data, copy_len); - } + if(copy_len) { memcpy(output_buffer + output_len, evt->data, copy_len); } } output_len += copy_len; } static void handle_http_on_finish(esp_http_client_event_t* evt) { ESP_LOGD(TAG, "ON_FINISH"); - if (output_buffer != NULL) { + if(output_buffer != NULL) { ESP_LOGV(TAG, "Response: %s", output_buffer); free(output_buffer); output_buffer = NULL; @@ -91,13 +79,12 @@ static void handle_http_on_finish(esp_http_client_event_t* evt) { static void handle_http_disconnected(esp_http_client_event_t* evt) { ESP_LOGI(TAG, "DISCONNECTED"); int mbedtls_err = 0; - esp_err_t err = - esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL); - if (err != 0) { + esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL); + if(err != 0) { ESP_LOGI(TAG, "Last error : %s", esp_err_to_name(err)); ESP_LOGI(TAG, "Last mbedtls err 0x%x", mbedtls_err); } - if (output_buffer != NULL) { + if(output_buffer != NULL) { free(output_buffer); output_buffer = NULL; } @@ -115,7 +102,7 @@ static const HttpEventHandler eventHandlers[] = { }; esp_err_t metrics_http_event_handler(esp_http_client_event_t* evt) { - if (evt->event_id < 0 || evt->event_id >= sizeof(eventHandlers) / sizeof(eventHandlers[0])) { + if(evt->event_id < 0 || evt->event_id >= sizeof(eventHandlers) / sizeof(eventHandlers[0])) { ESP_LOGE(TAG, "Invalid event ID: %d", evt->event_id); return ESP_FAIL; } @@ -138,20 +125,16 @@ int metrics_http_post_request(const char* payload, const char* url) { esp_http_client_handle_t client = esp_http_client_init(&config); esp_err_t err = esp_http_client_set_method(client, HTTP_METHOD_POST); - if (err == ESP_OK) { - err = esp_http_client_set_header(client, "Content-Type", "application/json"); - } - if (err == ESP_OK) { + if(err == ESP_OK) { err = esp_http_client_set_header(client, "Content-Type", "application/json"); } + if(err == ESP_OK) { ESP_LOGV(TAG, "Setting payload: %s", payload); err = esp_http_client_set_post_field(client, payload, strlen(payload)); } - if (err == ESP_OK) { - err = esp_http_client_perform(client); - } - if (err == ESP_OK) { + if(err == ESP_OK) { err = esp_http_client_perform(client); } + if(err == ESP_OK) { status_code = esp_http_client_get_status_code(client); - ESP_LOGD(TAG, "metrics call Status = %d, content_length = %d", - esp_http_client_get_status_code(client), esp_http_client_get_content_length(client)); + ESP_LOGD(TAG, "metrics call Status = %d, content_length = %d", esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); } else { status_code = 500; diff --git a/components/platform_config/Config.cpp b/components/platform_config/Config.cpp index ccedda64..0b276458 100644 --- a/components/platform_config/Config.cpp +++ b/components/platform_config/Config.cpp @@ -25,33 +25,34 @@ __attribute__((section(".ext_ram.bss"))) sys_dac_default_sets* default_dac_sets; __attribute__((section(".ext_ram.bss"))) System::PB configWrapper("config", &sys_config_msg, sizeof(sys_config_msg)); __attribute__((section(".ext_ram.bss"))) System::PB stateWrapper("state", &sys_state_data_msg, sizeof(sys_state_data_msg)); -__attribute__((section(".ext_ram.bss"))) System::PB defaultSets("default_sets", &sys_dac_default_sets_msg, sizeof(sys_dac_default_sets_msg)); +__attribute__((section(".ext_ram.bss"))) System::PB defaultSets( + "default_sets", &sys_dac_default_sets_msg, sizeof(sys_dac_default_sets_msg)); const int MaxDelay = 1000; bool config_update_mac_string(const pb_msgdesc_t* desc, uint32_t field_tag, void* message) { pb_field_iter_t iter; - if (pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { - if (!iter.pData) { + if(pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { + if(!iter.pData) { ESP_LOGW(TAG, "Unable to check mac string member. Data not initialized"); return false; } - if (iter.pData) { + if(iter.pData) { auto curvalue = std::string((char*)iter.pData); - if (curvalue.find(get_mac_str()) != std::string::npos) { + if(curvalue.find(get_mac_str()) != std::string::npos) { ESP_LOGD(TAG, "Entry already has mac string: %s", curvalue.c_str()); return true; } - if (curvalue.find("@@init_from_mac@@") == std::string::npos) { + if(curvalue.find("@@init_from_mac@@") == std::string::npos) { ESP_LOGW(TAG, "Member not configured for mac address or was overwritten: %s", curvalue.c_str()); return false; } auto newval = std::string("squeezelite-") + get_mac_str(); - if (PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { + if(PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { ESP_LOGD(TAG, "Field is a pointer. Freeing previous value if any: %s", STR_OR_BLANK((char*)iter.pField)); FREE_AND_NULL(*(char**)iter.pField); ESP_LOGD(TAG, "Field is a pointer. Setting new value as %s", newval.c_str()); *(char**)iter.pField = strdup_psram(newval.c_str()); - } else if (PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { + } else if(PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { ESP_LOGD(TAG, "Static string. Setting new value as %s from %s", newval.c_str(), STR_OR_BLANK((char*)iter.pData)); memset((char*)iter.pData, 0x00, iter.data_size); strncpy((char*)iter.pData, newval.c_str(), iter.data_size); @@ -64,7 +65,7 @@ bool config_update_mac_string(const pb_msgdesc_t* desc, uint32_t field_tag, void return true; } bool set_pb_string_from_mac(pb_ostream_t* stream, const pb_field_t* field, void* const* arg) { - if (!stream) { + if(!stream) { // This is a size calculation pass, return true to indicate field presence return true; } @@ -74,7 +75,7 @@ bool set_pb_string_from_mac(pb_ostream_t* stream, const pb_field_t* field, void* char* value = alloc_get_string_with_mac(prefix && strlen(prefix) > 0 ? prefix : "squeezelite-"); // Write the string to the stream - if (!pb_encode_string(stream, (uint8_t*)value, strlen(value))) { + if(!pb_encode_string(stream, (uint8_t*)value, strlen(value))) { free(value); // Free memory if encoding fails return false; } @@ -104,7 +105,7 @@ void set_mac_string() { changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, &config->names) || changed; changed = config_update_mac_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, &config->names) || changed; - if (changed) { + if(changed) { ESP_LOGI(TAG, "One or more name was changed. Committing"); configWrapper.RaiseChangedAsync(); } @@ -120,44 +121,42 @@ void config_load() { assert(platform != nullptr); assert(sys_state != nullptr); assert(default_dac_sets != nullptr); - + configWrapper.get()->net.credentials = reinterpret_cast(new WifiList("wifi")); assert(configWrapper.get()->net.credentials != nullptr); - if (!stateWrapper.FileExists()) { + if(!stateWrapper.FileExists()) { ESP_LOGI(TAG, "State file not found or is empty. "); stateWrapper.Reinitialize(true); stateWrapper.SetTarget(CONFIG_FW_PLATFORM_NAME); } else { stateWrapper.LoadFile(); } - if (!configWrapper.FileExists()) { + if(!configWrapper.FileExists()) { ESP_LOGI(TAG, "Configuration file not found or is empty. "); configWrapper.Reinitialize(true); ESP_LOGI(TAG, "Current device name after load: %s", platform->names.device); - - configWrapper.SetTarget(CONFIG_FW_PLATFORM_NAME,true); + + configWrapper.SetTarget(CONFIG_FW_PLATFORM_NAME, true); set_mac_string(); ESP_LOGW(TAG, "Restart required after initializing configuration"); restart = true; } else { configWrapper.LoadFile(); - if (configWrapper.GetTargetName().empty() && !std::string(CONFIG_FW_PLATFORM_NAME).empty()) { + if(configWrapper.GetTargetName().empty() && !std::string(CONFIG_FW_PLATFORM_NAME).empty()) { ESP_LOGW(TAG, "Config target is empty. Updating to %s", CONFIG_FW_PLATFORM_NAME); - configWrapper.Reinitialize(false,true,std::string(CONFIG_FW_PLATFORM_NAME)); + configWrapper.Reinitialize(false, true, std::string(CONFIG_FW_PLATFORM_NAME)); ESP_LOGW(TAG, "Restart required due to target change"); restart = true; } } - if (!defaultSets.FileExists()) { + if(!defaultSets.FileExists()) { ESP_LOGE(TAG, "Default Sets file not found or is empty. (%s)", defaultSets.GetFileName().c_str()); } else { defaultSets.LoadFile(); - } - if (restart) { - network_async_reboot(OTA); } + if(restart) { network_async_reboot(OTA); } } void config_dump_config() { auto serialized = configWrapper.Encode(); @@ -167,14 +166,14 @@ void config_dump_config() { void config_set_target(const char* target_name, bool reset) { std::string new_target = std::string(target_name); bool restart = false; - if (configWrapper.GetTargetName() != new_target) { + if(configWrapper.GetTargetName() != new_target) { ESP_LOGI(TAG, "Setting configuration target name to %s, %s", target_name, reset ? "full reset" : "reapply only"); - if (reset) { + if(reset) { ESP_LOGD(TAG, "Reinitializing Config structure"); - configWrapper.Reinitialize(false,true,new_target); + configWrapper.Reinitialize(false, true, new_target); } else { ESP_LOGD(TAG, "Loading Config target values for %s", target_name); - configWrapper.SetTarget(target_name,true); + configWrapper.SetTarget(target_name, true); configWrapper.LoadTargetValues(); configWrapper.RaiseChangedAsync(); } @@ -182,28 +181,26 @@ void config_set_target(const char* target_name, bool reset) { } else { ESP_LOGW(TAG, "Target name has no change"); } - if (stateWrapper.GetTargetName() != new_target) { + if(stateWrapper.GetTargetName() != new_target) { ESP_LOGI(TAG, "Setting state target name to %s, %s", target_name, reset ? "full reset" : "reapply only"); - restart=true; - if (reset) { + restart = true; + if(reset) { ESP_LOGD(TAG, "Reinitializing State structure"); - stateWrapper.Reinitialize(false,true,new_target); + stateWrapper.Reinitialize(false, true, new_target); } else { ESP_LOGD(TAG, "Loading State target values for %s", target_name); - stateWrapper.SetTarget(target_name,true); + stateWrapper.SetTarget(target_name, true); stateWrapper.LoadTargetValues(); stateWrapper.RaiseChangedAsync(); } } ESP_LOGD(TAG, "Done updating target to %s", target_name); - if(restart){ - network_async_reboot(RESTART); - } + if(restart) { network_async_reboot(RESTART); } } void config_set_target_no_reset(const char* target_name) { config_set_target(target_name, false); } void config_set_target_reset(const char* target_name) { config_set_target(target_name, true); } void config_raise_changed(bool sync) { - if (sync) { + if(sync) { configWrapper.CommitChanges(); } else { configWrapper.RaiseChangedAsync(); @@ -226,7 +223,7 @@ bool config_http_send_config(httpd_req_t* req) { auto data = configWrapper.Encode(); httpd_resp_send(req, (const char*)data.data(), data.size()); return true; - } catch (const std::runtime_error& e) { + } catch(const std::runtime_error& e) { std::string errdesc = (std::string("Unable to get configuration: ") + e.what()); httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, errdesc.c_str()); } @@ -235,30 +232,26 @@ bool config_http_send_config(httpd_req_t* req) { bool system_set_string(const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value) { pb_field_iter_t iter; - ESP_LOGD(TAG,"system_set_string. Getting new value"); + ESP_LOGD(TAG, "system_set_string. Getting new value"); std::string newval = std::string(STR_OR_BLANK(value)); - ESP_LOGD(TAG,"system_set_string. Done getting new value"); + ESP_LOGD(TAG, "system_set_string. Done getting new value"); ESP_LOGD(TAG, "Setting value [%s] in message field tag %d", newval.c_str(), field_tag); - if (pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { - std::string old= std::string((char*)iter.pData); - if (iter.pData && old == newval) { + if(pb_field_iter_begin(&iter, desc, message) && pb_field_iter_find(&iter, field_tag)) { + std::string old = std::string((char*)iter.pData); + if(iter.pData && old == newval) { ESP_LOGW(TAG, "No change, from and to values are the same: [%s]", newval.c_str()); return false; } - if (PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { + if(PB_ATYPE(iter.type) == PB_ATYPE_POINTER) { ESP_LOGD(TAG, "Field is a pointer. Freeing previous value if any: %s", STR_OR_BLANK((char*)iter.pField)); FREE_AND_NULL(*(char**)iter.pField); ESP_LOGD(TAG, "Field is a pointer. Setting new value "); - if (!newval.empty()) { - *(char**)iter.pField = strdup_psram(newval.c_str()); - } + if(!newval.empty()) { *(char**)iter.pField = strdup_psram(newval.c_str()); } - } else if (PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { + } else if(PB_ATYPE(iter.type) == PB_ATYPE_STATIC) { ESP_LOGD(TAG, "Static string. Setting new value. Existing value: %s", (char*)iter.pData); memset((char*)iter.pData, 0x00, iter.data_size); - if (!newval.empty()) { - strncpy((char*)iter.pData, newval.c_str(), iter.data_size); - } + if(!newval.empty()) { strncpy((char*)iter.pData, newval.c_str(), iter.data_size); } } ESP_LOGD(TAG, "Done setting value "); } diff --git a/components/platform_config/Config.h b/components/platform_config/Config.h index 40b819ae..e995769e 100644 --- a/components/platform_config/Config.h +++ b/components/platform_config/Config.h @@ -16,8 +16,8 @@ extern System::PB stateWrapper; extern System::PB configWrapper; extern "C" { #endif -#define PLATFORM_GET_PTR(base, sname) \ - { \ +#define PLATFORM_GET_PTR(base, sname) \ + { \ (base && (base)->##has_##(sname) ? &(base)->sname : NULL) #define PLATFORM_DEVICES PLATFORM_GET_PTR(platform) void config_load(); @@ -31,19 +31,16 @@ void config_set_target(const char* target_name); void config_set_target_no_reset(const char* target_name); void config_set_target_reset(const char* target_name); -void config_commit_protowrapper(void * protoWrapper); +void config_commit_protowrapper(void* protoWrapper); bool config_http_send_config(httpd_req_t* req); bool config_erase_config(); void set_mac_string(); void config_dump_config(); -bool system_set_string( - const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value); +bool system_set_string(const pb_msgdesc_t* desc, uint32_t field_tag, void* message, const char* value); extern sys_config* platform; extern sys_state_data* sys_state; extern sys_config* presets; #ifdef __cplusplus } - #endif - diff --git a/components/platform_config/Locking.cpp b/components/platform_config/Locking.cpp index 078574d9..add3281e 100644 --- a/components/platform_config/Locking.cpp +++ b/components/platform_config/Locking.cpp @@ -14,15 +14,11 @@ Locking* Locking::Create(std::string name) { return new Locking(name); } void Locking::Destroy(Locking* lock) { delete lock; } -LockingHandle* Locking_Create(const char* name) { - return reinterpret_cast(Locking::Create(std::string(name))); -} +LockingHandle* Locking_Create(const char* name) { return reinterpret_cast(Locking::Create(std::string(name))); } void Locking_Destroy(LockingHandle* lock) { Locking::Destroy(reinterpret_cast(lock)); } -bool Locking_Lock(LockingHandle* lock, TickType_t maxWait_ms) { - return reinterpret_cast(lock)->Lock(maxWait_ms); -} +bool Locking_Lock(LockingHandle* lock, TickType_t maxWait_ms) { return reinterpret_cast(lock)->Lock(maxWait_ms); } void Locking_Unlock(LockingHandle* lock) { reinterpret_cast(lock)->Unlock(); } @@ -31,7 +27,7 @@ bool Locking_IsLocked(LockingHandle* lock) { return reinterpret_cast(l bool Locking::Lock(TickType_t maxWait_ms) { assert(_mutex != nullptr); ESP_LOGV(TAG, "Locking %s", _name.c_str()); - if (xSemaphoreTakeRecursive(_mutex, pdMS_TO_TICKS(maxWait_ms)) == pdTRUE) { + if(xSemaphoreTakeRecursive(_mutex, pdMS_TO_TICKS(maxWait_ms)) == pdTRUE) { ESP_LOGV(TAG, "locked %s", _name.c_str()); return true; } else { diff --git a/components/platform_config/Locking.h b/components/platform_config/Locking.h index 5be78646..3193f2be 100644 --- a/components/platform_config/Locking.h +++ b/components/platform_config/Locking.h @@ -55,7 +55,7 @@ class Locking { static void Destroy(Locking* lock); }; -} // namespace PlatformConfig +} // namespace System extern "C" { #endif diff --git a/components/platform_config/PBW.cpp b/components/platform_config/PBW.cpp index f31e45dd..0093a6d8 100644 --- a/components/platform_config/PBW.cpp +++ b/components/platform_config/PBW.cpp @@ -28,19 +28,19 @@ bool PBHelper::SetGroupBit(Flags flags, bool flag) { bool result = true; int bit_num = static_cast(flags); int curFlags = xEventGroupGetBits(_group); - if ((curFlags & static_cast(Flags::LOAD)) && flags == Flags::COMMITTED) { + if((curFlags & static_cast(Flags::LOAD)) && flags == Flags::COMMITTED) { ESP_LOGD(PROTOTAG, "Loading %s, ignoring changes", name.c_str()); result = false; } - if (result) { - if ((curFlags & bit_num) == flag) { + if(result) { + if((curFlags & bit_num) == flag) { ESP_LOGV(PROTOTAG, "Flag %d already %s", bit_num, flag ? "Set" : "Cleared"); result = false; } } - if (result) { + if(result) { ESP_LOGV(PROTOTAG, "%s Flag %d ", flag ? "Setting" : "Clearing", bit_num); - if (!flag) { + if(!flag) { xEventGroupClearBits(_group, bit_num); } else { xEventGroupSetBits(_group, bit_num); @@ -51,139 +51,106 @@ bool PBHelper::SetGroupBit(Flags flags, bool flag) { void PBHelper::SyncCommit(void* protoWrapper) { IPBBase* protoWrapperBase = reinterpret_cast(protoWrapper); - if (protoWrapperBase) { - protoWrapperBase->CommitChanges(); - } + if(protoWrapperBase) { protoWrapperBase->CommitChanges(); } } -std::vector PBHelper::EncodeData( - const pb_msgdesc_t* fields, const void* src_struct) { +std::vector PBHelper::EncodeData(const pb_msgdesc_t* fields, const void* src_struct) { size_t datasz; ESP_LOGV(PROTOTAG, "EncodeData: getting size"); - if (!pb_get_encoded_size(&datasz, fields, src_struct)) { - throw std::runtime_error("Failed to get encoded size."); - } + if(!pb_get_encoded_size(&datasz, fields, src_struct)) { throw std::runtime_error("Failed to get encoded size."); } ESP_LOGV(PROTOTAG, "EncodeData: size: %d. Encoding", datasz); std::vector data(datasz); pb_ostream_t stream = pb_ostream_from_buffer(data.data(), datasz); - if (!pb_encode(&stream, fields, src_struct)) { - throw std::runtime_error("Failed to encode data."); - } + if(!pb_encode(&stream, fields, src_struct)) { throw std::runtime_error("Failed to encode data."); } ESP_LOGV(PROTOTAG, "EncodeData: Done"); return data; } -void PBHelper::DecodeData( - std::vector data, const pb_msgdesc_t* fields, void* target, bool noinit) { +void PBHelper::DecodeData(std::vector data, const pb_msgdesc_t* fields, void* target, bool noinit) { pb_istream_t stream = pb_istream_from_buffer((uint8_t*)data.data(), data.size()); bool result = false; // Decode the Protocol Buffers message - if (noinit) { + if(noinit) { ESP_LOGD(PROTOTAG, "Decoding WITHOUT initialization"); result = pb_decode_noinit(&stream, fields, data.data()); } else { ESP_LOGD(PROTOTAG, "Decoding WITH initialization"); result = pb_decode(&stream, fields, target); } - if (!result) { - throw std::runtime_error( - std::string("Failed to decode settings: %s", PB_GET_ERROR(&stream))); - } + if(!result) { throw std::runtime_error(std::string("Failed to decode settings: %s", PB_GET_ERROR(&stream))); } ESP_LOGD(PROTOTAG, "Data decoded"); } -void PBHelper::CommitFile( - const std::string& filename, const pb_msgdesc_t* fields, const void* src_struct) { +void PBHelper::CommitFile(const std::string& filename, const pb_msgdesc_t* fields, const void* src_struct) { size_t datasz = 0; ESP_LOGD(PROTOTAG, "Committing data to file File %s", filename.c_str()); + if(!pb_get_encoded_size(&datasz, fields, src_struct)) { throw std::runtime_error("Failed to get encoded size."); } - if (!pb_get_encoded_size(&datasz, fields, src_struct)) { - throw std::runtime_error("Failed to get encoded size."); - } - - if (datasz == 0) { + if(datasz == 0) { ESP_LOGW(PROTOTAG, "File %s not written. Data size is zero", filename.c_str()); return; } ESP_LOGD(PROTOTAG, "Committing to file %s", filename.c_str()); - if (!src_struct) { - throw std::runtime_error("Null pointer received."); - } + if(!src_struct) { throw std::runtime_error("Null pointer received."); } FILE* file = fopen(filename.c_str(), "wb"); - if (file == nullptr) { - throw std::runtime_error(std::string("Error opening file ") + filename.c_str()); - } + if(file == nullptr) { throw std::runtime_error(std::string("Error opening file ") + filename.c_str()); } pb_ostream_t filestream = PB_OSTREAM_SIZING; filestream.callback = &out_file_binding; filestream.state = file; filestream.max_size = SIZE_MAX; ESP_LOGD(PROTOTAG, "Starting file encode for %s", filename.c_str()); - if (!pb_encode(&filestream, fields, (void*)src_struct)) { + if(!pb_encode(&filestream, fields, (void*)src_struct)) { fclose(file); throw std::runtime_error("Encoding file failed"); } ESP_LOGD(PROTOTAG, "Encoded size: %d", filestream.bytes_written); - if (filestream.bytes_written == 0) { - ESP_LOGW(PROTOTAG, "Empty structure for file %s", filename.c_str()); - } + if(filestream.bytes_written == 0) { ESP_LOGW(PROTOTAG, "Empty structure for file %s", filename.c_str()); } fclose(file); } -bool PBHelper::IsDataDifferent( - const pb_msgdesc_t* fields, const void* src_struct, const void* other_struct) { +bool PBHelper::IsDataDifferent(const pb_msgdesc_t* fields, const void* src_struct, const void* other_struct) { bool changed = false; try { ESP_LOGV(PROTOTAG, "Encoding Source data"); auto src_data = EncodeData(fields, src_struct); ESP_LOGV(PROTOTAG, "Encoding Compared data"); auto other_data = EncodeData(fields, other_struct); - if (src_data.size() != other_data.size()) { - ESP_LOGD(PROTOTAG, "IsDataDifferent: source and target size different: [%d!=%d]", - src_data.size(), other_data.size()); + if(src_data.size() != other_data.size()) { + ESP_LOGD(PROTOTAG, "IsDataDifferent: source and target size different: [%d!=%d]", src_data.size(), other_data.size()); changed = true; - } else if (src_data != other_data) { + } else if(src_data != other_data) { ESP_LOGD(PROTOTAG, "IsDataDifferent: source and target not the same"); changed = true; } - if (changed && esp_log_level_get(PROTOTAG) >= ESP_LOG_DEBUG) { + if(changed && esp_log_level_get(PROTOTAG) >= ESP_LOG_DEBUG) { ESP_LOGD(PROTOTAG, "Source data: "); dump_data((const uint8_t*)src_data.data(), src_data.size()); ESP_LOGD(PROTOTAG, "Compared data: "); dump_data((const uint8_t*)other_data.data(), src_data.size()); } - } catch (const std::runtime_error& e) { - throw std::runtime_error(std::string("Comparison failed: ") + e.what()); - } + } catch(const std::runtime_error& e) { throw std::runtime_error(std::string("Comparison failed: ") + e.what()); } ESP_LOGD(PROTOTAG, "IsDataDifferent: %s", changed ? "TRUE" : "FALSE"); return changed; } -void PBHelper::CopyStructure( - const void* src_data, const pb_msgdesc_t* fields, void* target_data) { +void PBHelper::CopyStructure(const void* src_data, const pb_msgdesc_t* fields, void* target_data) { try { auto src = EncodeData(fields, src_data); ESP_LOGD(PROTOTAG, "Encoded structure to copy has %d bytes", src.size()); DecodeData(src, fields, target_data, false); - } catch (const std::runtime_error& e) { - throw std::runtime_error(std::string("Copy failed: ") + e.what()); - } + } catch(const std::runtime_error& e) { throw std::runtime_error(std::string("Copy failed: ") + e.what()); } } -void PBHelper::LoadFile( - const std::string& filename, const pb_msgdesc_t* fields, void* target_data, bool noinit) { +void PBHelper::LoadFile(const std::string& filename, const pb_msgdesc_t* fields, void* target_data, bool noinit) { struct stat fileInformation; - if (!get_file_info(&fileInformation, filename.c_str()) || fileInformation.st_size == 0) { - throw FileNotFoundException("filename"); - } + if(!get_file_info(&fileInformation, filename.c_str()) || fileInformation.st_size == 0) { throw FileNotFoundException("filename"); } FILE* file = fopen(filename.c_str(), "rb"); ESP_LOGI(PROTOTAG, "Loading file %s", filename.c_str()); - if (file == nullptr) { + if(file == nullptr) { int errNum = errno; - ESP_LOGE( - PROTOTAG, "Unable to open file: %s. Error: %s", filename.c_str(), strerror(errNum)); - throw std::runtime_error( - "Unable to open file: " + filename + ". Error: " + strerror(errNum)); + ESP_LOGE(PROTOTAG, "Unable to open file: %s. Error: %s", filename.c_str(), strerror(errNum)); + throw std::runtime_error("Unable to open file: " + filename + ". Error: " + strerror(errNum)); } pb_istream_t filestream = PB_ISTREAM_EMPTY; filestream.callback = &in_file_binding; @@ -192,7 +159,7 @@ void PBHelper::LoadFile( ESP_LOGV(PROTOTAG, "Starting decode."); bool result = false; - if (noinit) { + if(noinit) { ESP_LOGV(PROTOTAG, "Decoding WITHOUT initialization"); result = pb_decode_noinit(&filestream, fields, target_data); } else { @@ -200,9 +167,7 @@ void PBHelper::LoadFile( result = pb_decode(&filestream, fields, target_data); } fclose(file); - if (!result) { - throw System::DecodeError(PB_GET_ERROR(&filestream)); - } + if(!result) { throw System::DecodeError(PB_GET_ERROR(&filestream)); } ESP_LOGV(PROTOTAG, "Decode done."); } @@ -215,20 +180,17 @@ bool PBHelper::FileExists() { return FileExists(filename); } bool PBHelper::IsLoading() { return xEventGroupGetBits(_group) & static_cast(Flags::LOAD); } void PBHelper::SetLoading(bool active) { SetGroupBit(Flags::LOAD, active); } -bool PBHelper::WaitForCommit(uint8_t retries=2) { - auto remain= retries; +bool PBHelper::WaitForCommit(uint8_t retries = 2) { + auto remain = retries; auto bits = xEventGroupGetBits(_group); bool commit_pending = HasChanges(); - ESP_LOGD(PROTOTAG, "Entering WaitForCommit bits: %d, changes? %s", bits, - commit_pending ? "YES" : "NO"); - while (commit_pending && remain-->0) { + ESP_LOGD(PROTOTAG, "Entering WaitForCommit bits: %d, changes? %s", bits, commit_pending ? "YES" : "NO"); + while(commit_pending && remain-- > 0) { ESP_LOGD(PROTOTAG, "Waiting for config commit ..."); - auto bits = xEventGroupWaitBits( - _group, static_cast(Flags::COMMITTED), pdFALSE, pdTRUE, (MaxDelay * 2) / portTICK_PERIOD_MS); + auto bits = xEventGroupWaitBits(_group, static_cast(Flags::COMMITTED), pdFALSE, pdTRUE, (MaxDelay * 2) / portTICK_PERIOD_MS); commit_pending = !(bits & static_cast(Flags::COMMITTED)); - ESP_LOGD( - PROTOTAG, "WaitForCommit bits: %d, changes? %s", bits, commit_pending ? "YES" : "NO"); - if (commit_pending) { + ESP_LOGD(PROTOTAG, "WaitForCommit bits: %d, changes? %s", bits, commit_pending ? "YES" : "NO"); + if(commit_pending) { ESP_LOGW(PROTOTAG, "Timeout waiting for config commit for [%s]", name.c_str()); } else { ESP_LOGI(PROTOTAG, "Changes to %s committed", name.c_str()); @@ -238,30 +200,26 @@ bool PBHelper::WaitForCommit(uint8_t retries=2) { } void PBHelper::RaiseChangedAsync() { - if(_no_save){ - ESP_LOGD(PROTOTAG,"Ignoring changes for %s, as it is marked not to be saved", name.c_str()); - } + if(_no_save) { ESP_LOGD(PROTOTAG, "Ignoring changes for %s, as it is marked not to be saved", name.c_str()); } ESP_LOGI(PROTOTAG, "Changes made to %s", name.c_str()); - if (IsLoading()) { + if(IsLoading()) { ESP_LOGD(PROTOTAG, "Ignoring raise modified during load of %s", name.c_str()); } else { SetGroupBit(Flags::COMMITTED, false); - network_async_commit_protowrapper( - static_cast(static_cast(this))); + network_async_commit_protowrapper(static_cast(static_cast(this))); } } const std::string& PBHelper::GetFileName() { return filename; } bool PBHelper::HasChanges() { return !(xEventGroupGetBits(_group) & static_cast(Flags::COMMITTED)); } -} // namespace PlatformConfig +} // namespace System -bool proto_load_file( - const char* filename, const pb_msgdesc_t* fields, void* target_data, bool noinit = false) { +bool proto_load_file(const char* filename, const pb_msgdesc_t* fields, void* target_data, bool noinit = false) { try { - ESP_LOGI(System::PBHelper::PROTOTAG,"Loading file %s",filename); + ESP_LOGI(System::PBHelper::PROTOTAG, "Loading file %s", filename); System::PBHelper::LoadFile(std::string(filename), fields, target_data, noinit); - } catch (const std::exception& e) { - if(!noinit){ - // initialize the structure + } catch(const std::exception& e) { + if(!noinit) { + // initialize the structure pb_istream_t stream = pb_istream_from_buffer(nullptr, 0); pb_decode(&stream, fields, target_data); } diff --git a/components/platform_config/PBW.h b/components/platform_config/PBW.h index 7de4f268..2207d84a 100644 --- a/components/platform_config/PBW.h +++ b/components/platform_config/PBW.h @@ -71,7 +71,7 @@ class PBHelper : public IPBBase { std::string filename; static const int MaxDelay = 1000; Locking _lock; - size_t _datasize; + size_t _datasize; bool _no_save; public: @@ -80,28 +80,22 @@ class PBHelper : public IPBBase { static const char* PROTOTAG; std::string& GetName() { return name; } const char* GetCName() { return name.c_str(); } - static std::string GetDefFileName(std::string name){ - return std::string(spiffs_base_path) + "/data/def_" + name + ".bin"; - } - std::string GetDefFileName(){ - return GetDefFileName(this->name); - } - size_t GetDataSize(){ - return _datasize; - } + static std::string GetDefFileName(std::string name) { return std::string(spiffs_base_path) + "/data/def_" + name + ".bin"; } + std::string GetDefFileName() { return GetDefFileName(this->name); } + size_t GetDataSize() { return _datasize; } PBHelper(std::string name, const pb_msgdesc_t* fields, size_t defn_size, size_t datasize, bool no_save = false) - : _fields(fields), _group(xEventGroupCreate()), name(std::move(name)), _lock(this->name),_datasize(datasize), _no_save(no_save) { + : _fields(fields), _group(xEventGroupCreate()), name(std::move(name)), _lock(this->name), _datasize(datasize), _no_save(no_save) { sys_message_def definition = sys_message_def_init_default; bool savedef = false; - ESP_LOGD(PROTOTAG,"Getting definition file name"); + ESP_LOGD(PROTOTAG, "Getting definition file name"); auto deffile = GetDefFileName(); - ESP_LOGD(PROTOTAG,"Instantiating with definition size %d and data size %d", defn_size,datasize); - + ESP_LOGD(PROTOTAG, "Instantiating with definition size %d and data size %d", defn_size, datasize); + try { PBHelper::LoadFile(deffile, &sys_message_def_msg, static_cast(&definition)); - if (definition.data->size != defn_size || definition.datasize != _datasize) { + if(definition.data->size != defn_size || definition.datasize != _datasize) { ESP_LOGW(PROTOTAG, "Structure definition %s has changed", this->name.c_str()); - if (!is_recovery_running) { + if(!is_recovery_running) { savedef = true; pb_release(&sys_message_def_msg, &definition); } else { @@ -110,20 +104,18 @@ class PBHelper : public IPBBase { _datasize = definition.datasize; } } - } catch (const FileNotFoundException& e) { - savedef = true; - } + } catch(const FileNotFoundException& e) { savedef = true; } - if (savedef) { + if(savedef) { ESP_LOGW(PROTOTAG, "Saving definition for structure %s", this->name.c_str()); - auto data = (pb_bytes_array_t*)malloc_init_external(sizeof(pb_bytes_array_t)+defn_size); + auto data = (pb_bytes_array_t*)malloc_init_external(sizeof(pb_bytes_array_t) + defn_size); memcpy(&data->bytes, fields, defn_size); data->size = defn_size; definition.data = data; definition.datasize = _datasize; - ESP_LOGD(PROTOTAG,"Committing structure with %d bytes ",data->size); + ESP_LOGD(PROTOTAG, "Committing structure with %d bytes ", data->size); PBHelper::CommitFile(deffile, &sys_message_def_msg, &definition); - ESP_LOGD(PROTOTAG,"Releasing memory"); + ESP_LOGD(PROTOTAG, "Releasing memory"); free(data); } } @@ -140,23 +132,21 @@ class PBHelper : public IPBBase { bool FileExists(); bool IsLoading(); void SetLoading(bool active); - bool WaitForCommit(uint8_t retries ); + bool WaitForCommit(uint8_t retries); void RaiseChangedAsync(); const std::string& GetFileName(); bool HasChanges(); }; template class PB : public PBHelper { private: - T *_root; + T* _root; // Generic _setTarget implementation void _setTarget(std::string target, std::false_type) { ESP_LOGE(PROTOTAG, "Setting target not implemented for %s", name.c_str()); } // Special handling for sys_config void _setTarget(std::string target, std::true_type) { - if (_root->target) { - free(_root->target); - } + if(_root->target) { free(_root->target); } _root->target = strdup_psram(target.c_str()); } std::string _getTargetName(std::false_type) { return ""; } @@ -168,12 +158,12 @@ template class PB : public PBHelper { // Const accessor for the underlying structure const T& Root() const { return *_root; } - T* get() { return _root; } + T* get() { return _root; } const T* get() const { return (const T*)_root; } // Constructor - explicit PB(std::string name, const pb_msgdesc_t* fields, size_t defn_size, bool no_save = false) : - PBHelper(std::move(name), fields,defn_size, sizeof(T), no_save) { + explicit PB(std::string name, const pb_msgdesc_t* fields, size_t defn_size, bool no_save = false) + : PBHelper(std::move(name), fields, defn_size, sizeof(T), no_save) { ESP_LOGD(PROTOTAG, "Instantiating PB class for %s with data size %d", this->name.c_str(), sizeof(T)); ResetModified(); filename = std::string(spiffs_base_path) + "/data/" + this->name + ".bin"; @@ -186,14 +176,14 @@ template class PB : public PBHelper { std::string newtarget = trim(targetname); std::string currenttarget = trim(GetTargetName()); ESP_LOGD(PROTOTAG, "SetTarget called with %s", newtarget.c_str()); - if (newtarget == currenttarget && !newtarget.empty()) { + if(newtarget == currenttarget && !newtarget.empty()) { ESP_LOGD(PROTOTAG, "Target name %s not changed for %s", currenttarget.c_str(), name.c_str()); - } else if (newtarget.empty() && !currenttarget.empty()) { + } else if(newtarget.empty() && !currenttarget.empty()) { ESP_LOGW(PROTOTAG, "Target name %s was removed for %s ", currenttarget.c_str(), name.c_str()); } ESP_LOGI(PROTOTAG, "Setting target %s for %s", newtarget.c_str(), name.c_str()); _setTarget(newtarget, has_target_implementation{}); - if (!skip_commit) { + if(!skip_commit) { ESP_LOGD(PROTOTAG, "Raising changed flag to commit new target name."); RaiseChangedAsync(); } else { @@ -201,9 +191,7 @@ template class PB : public PBHelper { } } std::string GetTargetFileName() { - if (GetTargetName().empty()) { - return ""; - } + if(GetTargetName().empty()) { return ""; } auto target_name = GetTargetName(); return std::string(spiffs_base_path) + "/targets/" + toLowerStr(target_name) + "/" + name + ".bin"; } @@ -218,33 +206,25 @@ template class PB : public PBHelper { std::string fullpath = std::string(spiffs_base_path) + "/defaults/" + this->name + ".bin"; ESP_LOGD(PROTOTAG, "Attempting to load defaults file for %s", fullpath.c_str()); PBHelper::LoadFile(fullpath.c_str(), _fields, static_cast(_root), true); - } catch (FileNotFoundException&) { - ESP_LOGW(PROTOTAG, "No defaults found for %s", name.c_str()); - } catch (std::runtime_error& e) { + } catch(FileNotFoundException&) { ESP_LOGW(PROTOTAG, "No defaults found for %s", name.c_str()); } catch(std::runtime_error& e) { ESP_LOGE(PROTOTAG, "Error loading Target %s overrides file: %s", GetTargetName().c_str(), e.what()); } SetLoading(false); - if (!skip_target) { - if (!target_name.empty()) { - SetTarget(target_name, true); - } + if(!skip_target) { + if(!target_name.empty()) { SetTarget(target_name, true); } LoadTargetValues(); } - if (commit) { - CommitChanges(); - } + if(commit) { CommitChanges(); } } void LoadFile(bool skip_target = false, bool noinit = false) { SetLoading(true); PBHelper::LoadFile(filename, _fields, static_cast(_root), noinit); SetLoading(false); - if (!skip_target) { - LoadTargetValues(); - } + if(!skip_target) { LoadTargetValues(); } } void LoadTargetValues() { ESP_LOGD(PROTOTAG, "Loading target %s values for %s", GetTargetName().c_str(), name.c_str()); - if (GetTargetFileName().empty()) { + if(GetTargetFileName().empty()) { ESP_LOGD(PROTOTAG, "No target file to load for %s", name.c_str()); return; } @@ -261,23 +241,20 @@ template class PB : public PBHelper { // } SetGroupBit(Flags::COMMITTED, false); - } catch (FileNotFoundException&) { + } catch(FileNotFoundException&) { ESP_LOGD(PROTOTAG, "Target %s overrides file not found for %s", GetTargetName().c_str(), name.c_str()); - } catch (std::runtime_error& e) { - ESP_LOGE(PROTOTAG, "Error loading Target %s overrides file: %s", GetTargetName().c_str(), e.what()); - } + } catch(std::runtime_error& e) { ESP_LOGE(PROTOTAG, "Error loading Target %s overrides file: %s", GetTargetName().c_str(), e.what()); } } void CommitChanges() override { ESP_LOGI(PROTOTAG, "Committing %s to flash.", name.c_str()); - if (!_lock.Lock()) { + if(!_lock.Lock()) { ESP_LOGE(PROTOTAG, "Unable to lock config for commit "); return; } ESP_LOGV(PROTOTAG, "Config Locked. Committing"); try { CommitFile(filename, _fields, _root); - } catch (...) { - } + } catch(...) {} ResetModified(); _lock.Unlock(); ESP_LOGI(PROTOTAG, "Done committing %s to flash.", name.c_str()); @@ -286,16 +263,14 @@ template class PB : public PBHelper { void Unlock() { return _lock.Unlock(); } std::vector Encode() { auto data = std::vector(); - if (!_lock.Lock()) { - throw std::runtime_error("Unable to lock object"); - } + if(!_lock.Lock()) { throw std::runtime_error("Unable to lock object"); } data = EncodeData(_fields, this->_root); _lock.Unlock(); return data; } void CopyTo(T& target_data) { - if (!_lock.Lock()) { + if(!_lock.Lock()) { ESP_LOGE(PROTOTAG, "Lock failed for %s", name.c_str()); throw std::runtime_error("Lock failed "); } @@ -303,7 +278,7 @@ template class PB : public PBHelper { _lock.Unlock(); } void CopyFrom(const T& source_data) { - if (!_lock.Lock()) { + if(!_lock.Lock()) { ESP_LOGE(PROTOTAG, "Lock failed for %s", name.c_str()); throw std::runtime_error("Lock failed "); } @@ -321,7 +296,7 @@ template <> struct has_target_implementation : std::true_type {}; template <> struct has_target_implementation : std::true_type {}; -} // namespace PlatformConfig +} // namespace System extern "C" { #endif bool proto_load_file(const char* filename, const pb_msgdesc_t* fields, void* target_data, bool noinit); diff --git a/components/platform_config/WifiList.cpp b/components/platform_config/WifiList.cpp index 4323156e..de10d73c 100644 --- a/components/platform_config/WifiList.cpp +++ b/components/platform_config/WifiList.cpp @@ -14,37 +14,33 @@ bool sys_net_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const WifiList** managerPtr = static_cast(field->pData); WifiList* manager = *managerPtr; - if (istream != NULL && (field->tag == sys_net_config_credentials_tag || field->tag == sys_status_wifi_scan_result_tag)) { - if (manager == nullptr) { + if(istream != NULL && (field->tag == sys_net_config_credentials_tag || field->tag == sys_status_wifi_scan_result_tag)) { + if(manager == nullptr) { ESP_LOGE(TAG_CRED_MANAGER, "Invalid pointer to wifi list manager"); return false; } ESP_LOGV(TAG_CRED_MANAGER, "Decoding credentials"); sys_net_wifi_entry entry = sys_net_wifi_entry_init_default; - if (!pb_decode(istream, &sys_net_wifi_entry_msg, &entry)) return false; + if(!pb_decode(istream, &sys_net_wifi_entry_msg, &entry)) return false; printf("\nFound ssid %s, password %s\n", entry.ssid, entry.password); try { manager->AddUpdate(entry); // Add to the manager - } catch (const std::exception& e) { + } catch(const std::exception& e) { ESP_LOGE(TAG_CRED_MANAGER, "decode exception: %s", e.what()); return false; } ESP_LOGV(TAG_CRED_MANAGER, "Credentials decoding completed"); - } else if (ostream != NULL && (field->tag == sys_net_config_credentials_tag || field->tag == sys_status_wifi_scan_result_tag)) { - if (manager == nullptr) { + } else if(ostream != NULL && (field->tag == sys_net_config_credentials_tag || field->tag == sys_status_wifi_scan_result_tag)) { + if(manager == nullptr) { ESP_LOGV(TAG_CRED_MANAGER, "No wifi entries manager instance. nothing to encode"); return true; } ESP_LOGV(TAG_CRED_MANAGER, "Encoding %d access points", manager->GetCount()); - for (int i = 0; i < manager->GetCount(); i++) { + for(int i = 0; i < manager->GetCount(); i++) { ESP_LOGV(TAG_CRED_MANAGER, "Encoding credential #%d: SSID: %s, PASS: %s", i, manager->GetIndex(i)->ssid, manager->GetIndex(i)->password); - if (!pb_encode_tag_for_field(ostream, field)) { - return false; - } - if (!pb_encode_submessage(ostream, &sys_net_wifi_entry_msg, manager->GetIndex(i))) { - return false; - } + if(!pb_encode_tag_for_field(ostream, field)) { return false; } + if(!pb_encode_submessage(ostream, &sys_net_wifi_entry_msg, manager->GetIndex(i))) { return false; } } ESP_LOGV(TAG_CRED_MANAGER, "Credentials encoding completed"); } @@ -52,7 +48,7 @@ bool sys_net_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const return true; } std::string WifiList::GetBSSID(const wifi_event_sta_connected_t* evt) { - char buffer[18]={}; + char buffer[18] = {}; FormatBSSID(buffer, sizeof(buffer), evt->bssid); ESP_LOGD(TAG_CRED_MANAGER, "Formatted BSSID: %s", buffer); return std::string(buffer); @@ -63,11 +59,11 @@ bool WifiList::OffsetTimeStamp(google_protobuf_Timestamp* ts) { gettimeofday((struct timeval*)&tts, NULL); gts.nanos = tts.tv_usec * 1000; gts.seconds = tts.tv_sec; - if (tts.tv_sec < 1704143717) { + if(tts.tv_sec < 1704143717) { ESP_LOGE(TAG_CRED_MANAGER, "Error updating time stamp. Clock doesn't seem right"); return false; } - if (ts && ts->seconds < 1704143717) { + if(ts && ts->seconds < 1704143717) { ESP_LOGV(TAG_CRED_MANAGER, "Updating time stamp based on new clock value"); ts->seconds = gts.seconds - ts->seconds; ts->nanos = gts.nanos - ts->nanos; @@ -84,7 +80,7 @@ bool WifiList::UpdateTimeStamp(google_protobuf_Timestamp* ts, bool& has_flag_val gettimeofday((struct timeval*)&tts, NULL); gts.nanos = tts.tv_usec * 1000; gts.seconds = tts.tv_sec; - if (!has_flag_val || gts.nanos != ts->nanos || gts.seconds != ts->seconds) { + if(!has_flag_val || gts.nanos != ts->nanos || gts.seconds != ts->seconds) { ts->seconds = gts.seconds; ts->nanos = gts.nanos; has_flag_val = true; @@ -94,22 +90,16 @@ bool WifiList::UpdateTimeStamp(google_protobuf_Timestamp* ts, bool& has_flag_val } bool WifiList::isEmpty(const char* str, size_t len) { - for (size_t i = 0; i < len; ++i) { - if (str[i] != '\0') { - return false; - } + for(size_t i = 0; i < len; ++i) { + if(str[i] != '\0') { return false; } } return true; } bool WifiList::Update(const wifi_ap_record_t* ap, bool connected) { - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } auto existing = Get(ap); - if (!existing) { - return false; - } + if(!existing) { return false; } auto updated = ToSTAEntry(ap); updated.connected = connected; bool changed = Update(*existing, updated); @@ -121,39 +111,39 @@ bool WifiList::Update(sys_net_wifi_entry& existingEntry, sys_net_wifi_entry& upd // Check if any relevant fields have changed bool hasChanged = false; - if (!isEmpty(updated.ssid, sizeof(updated.ssid)) && memcmp(existingEntry.ssid, updated.ssid, sizeof(existingEntry.ssid)) != 0) { + if(!isEmpty(updated.ssid, sizeof(updated.ssid)) && memcmp(existingEntry.ssid, updated.ssid, sizeof(existingEntry.ssid)) != 0) { memcpy(existingEntry.ssid, updated.ssid, sizeof(existingEntry.ssid)); hasChanged = true; } // Check and copy BSSID if the compared BSSID is not empty - if (!isEmpty(updated.bssid, sizeof(updated.bssid)) && strcmp(updated.bssid, "00:00:00:00:00:00") != 0 && + if(!isEmpty(updated.bssid, sizeof(updated.bssid)) && strcmp(updated.bssid, "00:00:00:00:00:00") != 0 && memcmp(existingEntry.bssid, updated.bssid, sizeof(existingEntry.bssid)) != 0) { memcpy(existingEntry.bssid, updated.bssid, sizeof(existingEntry.bssid)); hasChanged = true; } // Check and copy password if the compared password is not empty - if (!isEmpty(updated.password, sizeof(updated.password)) && + if(!isEmpty(updated.password, sizeof(updated.password)) && memcmp(existingEntry.password, updated.password, sizeof(existingEntry.password)) != 0) { memcpy(existingEntry.password, updated.password, sizeof(existingEntry.password)); hasChanged = true; } - if (existingEntry.channel != updated.channel && updated.channel > 0) { + if(existingEntry.channel != updated.channel && updated.channel > 0) { existingEntry.channel = updated.channel; hasChanged = true; } - if (existingEntry.auth_type != updated.auth_type && updated.auth_type != sys_net_auth_types_AUTH_UNKNOWN) { + if(existingEntry.auth_type != updated.auth_type && updated.auth_type != sys_net_auth_types_AUTH_UNKNOWN) { existingEntry.auth_type = updated.auth_type; hasChanged = true; } - if (areRadioTypesDifferent(existingEntry.radio_type, existingEntry.radio_type_count, updated.radio_type, updated.radio_type_count) && + if(areRadioTypesDifferent(existingEntry.radio_type, existingEntry.radio_type_count, updated.radio_type, updated.radio_type_count) && updated.radio_type_count > 0 && updated.radio_type[0] != sys_net_radio_types_UNKNOWN) { - if (existingEntry.radio_type != nullptr) { + if(existingEntry.radio_type != nullptr) { // Free the old radio_type array if it exists delete[] existingEntry.radio_type; } @@ -164,33 +154,33 @@ bool WifiList::Update(sys_net_wifi_entry& existingEntry, sys_net_wifi_entry& upd hasChanged = true; } - if (updated.has_last_try) { - if (memcmp(&existingEntry.last_try, &updated.last_try, sizeof(existingEntry.last_try)) != 0) { + if(updated.has_last_try) { + if(memcmp(&existingEntry.last_try, &updated.last_try, sizeof(existingEntry.last_try)) != 0) { memcpy(&existingEntry.last_try, &updated.last_try, sizeof(existingEntry.last_try)); hasChanged = true; } } - if (updated.has_last_seen) { - if (memcmp(&existingEntry.last_seen, &updated.last_seen, sizeof(existingEntry.last_seen)) != 0) { + if(updated.has_last_seen) { + if(memcmp(&existingEntry.last_seen, &updated.last_seen, sizeof(existingEntry.last_seen)) != 0) { memcpy(&existingEntry.last_seen, &updated.last_seen, sizeof(existingEntry.last_seen)); hasChanged = true; } } - if (existingEntry.has_last_seen != updated.has_last_seen && updated.has_last_seen) { + if(existingEntry.has_last_seen != updated.has_last_seen && updated.has_last_seen) { existingEntry.has_last_seen = updated.has_last_seen; hasChanged = true; } - if (existingEntry.has_last_try != updated.has_last_try && updated.has_last_try) { + if(existingEntry.has_last_try != updated.has_last_try && updated.has_last_try) { existingEntry.has_last_try = updated.has_last_try; hasChanged = true; } - if (existingEntry.connected != updated.connected && updated.connected) { + if(existingEntry.connected != updated.connected && updated.connected) { existingEntry.connected = updated.connected; hasChanged = true; } - if (existingEntry.rssi != updated.rssi && updated.rssi != 0) { + if(existingEntry.rssi != updated.rssi && updated.rssi != 0) { existingEntry.rssi = updated.rssi; hasChanged = true; } @@ -201,8 +191,8 @@ bool WifiList::Update(sys_net_wifi_entry& existingEntry, sys_net_wifi_entry& upd std::string WifiList::formatRadioTypes(const sys_net_radio_types* radioTypes, pb_size_t count) { std::string result; - for (pb_size_t i = 0; i < count; ++i) { - switch (radioTypes[i]) { + for(pb_size_t i = 0; i < count; ++i) { + switch(radioTypes[i]) { case sys_net_radio_types_PHY_11B: result += "B"; break; @@ -229,25 +219,21 @@ std::string WifiList::formatRadioTypes(const sys_net_radio_types* radioTypes, pb result += "U"; break; } - if (i < count - 1) { - result += ","; - } + if(i < count - 1) { result += ","; } } return result; } bool WifiList::Update(const wifi_sta_config_t* sta, bool connected) { - if (!sta) { + if(!sta) { return false; // Invalid input } - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } sys_net_wifi_entry* existingEntry = Get(sta); // If the entry does not exist, nothing to update - if (!existingEntry) { + if(!existingEntry) { Unlock(); return false; } @@ -255,28 +241,28 @@ bool WifiList::Update(const wifi_sta_config_t* sta, bool connected) { // Check if any relevant fields have changed bool hasChanged = false; - if (strlen(updated.ssid) > 0 && memcmp(existingEntry->ssid, updated.ssid, sizeof(existingEntry->ssid)) != 0) { + if(strlen(updated.ssid) > 0 && memcmp(existingEntry->ssid, updated.ssid, sizeof(existingEntry->ssid)) != 0) { memcpy(existingEntry->ssid, updated.ssid, sizeof(existingEntry->ssid)); hasChanged = true; } - if (strlen(updated.bssid) > 0 && strcmp(updated.bssid, "00:00:00:00:00:00") != 0 && + if(strlen(updated.bssid) > 0 && strcmp(updated.bssid, "00:00:00:00:00:00") != 0 && memcmp(existingEntry->bssid, updated.bssid, sizeof(existingEntry->bssid)) != 0) { memcpy(existingEntry->bssid, updated.bssid, sizeof(existingEntry->bssid)); hasChanged = true; } - if (existingEntry->channel != updated.channel) { + if(existingEntry->channel != updated.channel) { existingEntry->channel = updated.channel; hasChanged = true; } - if (existingEntry->auth_type != updated.auth_type && updated.auth_type != sys_net_auth_types_AUTH_UNKNOWN) { + if(existingEntry->auth_type != updated.auth_type && updated.auth_type != sys_net_auth_types_AUTH_UNKNOWN) { existingEntry->auth_type = updated.auth_type; hasChanged = true; } - if (areRadioTypesDifferent(existingEntry->radio_type, existingEntry->radio_type_count, updated.radio_type, updated.radio_type_count) && + if(areRadioTypesDifferent(existingEntry->radio_type, existingEntry->radio_type_count, updated.radio_type, updated.radio_type_count) && updated.radio_type_count > 0 && updated.radio_type[0] != sys_net_radio_types_UNKNOWN) { // Free the old radio_type array if it exists delete[] existingEntry->radio_type; @@ -289,43 +275,43 @@ bool WifiList::Update(const wifi_sta_config_t* sta, bool connected) { hasChanged = true; } - if (updated.has_last_try) { - if (memcmp(&existingEntry->last_try, &updated.last_try, sizeof(existingEntry->last_try)) != 0) { + if(updated.has_last_try) { + if(memcmp(&existingEntry->last_try, &updated.last_try, sizeof(existingEntry->last_try)) != 0) { memcpy(&existingEntry->last_try, &updated.last_try, sizeof(existingEntry->last_try)); hasChanged = true; } } - if (updated.has_last_seen) { - if (memcmp(&existingEntry->last_seen, &updated.last_seen, sizeof(existingEntry->last_seen)) != 0) { + if(updated.has_last_seen) { + if(memcmp(&existingEntry->last_seen, &updated.last_seen, sizeof(existingEntry->last_seen)) != 0) { memcpy(&existingEntry->last_seen, &updated.last_seen, sizeof(existingEntry->last_seen)); hasChanged = true; } } - if (existingEntry->has_last_try != updated.has_last_try) { + if(existingEntry->has_last_try != updated.has_last_try) { existingEntry->has_last_try = updated.has_last_try; hasChanged = true; } - if (existingEntry->has_last_seen != updated.has_last_seen) { + if(existingEntry->has_last_seen != updated.has_last_seen) { existingEntry->has_last_seen = updated.has_last_seen; hasChanged = true; } - if (existingEntry->connected != (connected | updated.connected)) { + if(existingEntry->connected != (connected | updated.connected)) { existingEntry->connected = connected | updated.connected; hasChanged = true; } - if (strlen(updated.password) == 0 && strlen(existingEntry->password) > 0) { + if(strlen(updated.password) == 0 && strlen(existingEntry->password) > 0) { ESP_LOGW(TAG_CRED_MANAGER, "Updated password is empty, while existing password is %s for %s. Ignoring.", existingEntry->password, existingEntry->ssid); } else { - if (memcmp(existingEntry->password, updated.password, sizeof(existingEntry->password)) != 0) { + if(memcmp(existingEntry->password, updated.password, sizeof(existingEntry->password)) != 0) { memcpy(existingEntry->password, updated.password, sizeof(existingEntry->password)); hasChanged = true; } } - if (existingEntry->rssi != updated.rssi && updated.rssi != 0) { + if(existingEntry->rssi != updated.rssi && updated.rssi != 0) { existingEntry->rssi = updated.rssi; hasChanged = true; } @@ -334,15 +320,11 @@ bool WifiList::Update(const wifi_sta_config_t* sta, bool connected) { return hasChanged; } sys_net_wifi_entry WifiList::ToSTAEntry(const sys_net_wifi_entry* sta) { - if (!sta) { - throw std::runtime_error("Null STA entry provided"); - } + if(!sta) { throw std::runtime_error("Null STA entry provided"); } sys_net_wifi_entry result = *sta; - if (result.radio_type_count > 0) { + if(result.radio_type_count > 0) { std::unique_ptr newRadioTypes(new sys_net_radio_types[result.radio_type_count]); - if (!newRadioTypes) { - throw std::runtime_error("Failed to allocate memory for radio types"); - } + if(!newRadioTypes) { throw std::runtime_error("Failed to allocate memory for radio types"); } memcpy(newRadioTypes.get(), sta->radio_type, sizeof(sys_net_radio_types) * result.radio_type_count); result.radio_type = newRadioTypes.release(); } else { @@ -358,20 +340,18 @@ sys_net_wifi_entry WifiList::ToSTAEntry(const wifi_sta_config_t* sta, sys_net_au sys_net_wifi_entry WifiList::ToSTAEntry( const wifi_sta_config_t* sta, const std::list& radio_types, sys_net_auth_types auth_type) { sys_net_wifi_entry item = sys_net_wifi_entry_init_default; - ESP_LOGD(TAG_CRED_MANAGER,"%s (sta_config)","toSTAEntry"); + ESP_LOGD(TAG_CRED_MANAGER, "%s (sta_config)", "toSTAEntry"); auto result = ToSTAEntry(sta, item, radio_types); ESP_LOGV(TAG_CRED_MANAGER, "ToSTAEntry: SSID: %s, PASS: %s", result.ssid, result.password); return result; } sys_net_wifi_entry& WifiList::ToSTAEntry(const wifi_ap_record_t* ap, sys_net_wifi_entry& item) { - if (ap) { + if(ap) { auto radioTypes = GetRadioTypes(ap); - item.radio_type_count=radioTypes.size(); + item.radio_type_count = radioTypes.size(); item.radio_type = new sys_net_radio_types[item.radio_type_count]; int i = 0; - for (const auto& type : radioTypes) { - item.radio_type[i++] = type; - } + for(const auto& type : radioTypes) { item.radio_type[i++] = type; } item.auth_type = GetAuthType(ap); FormatBSSID(ap, item); item.channel = ap->primary; @@ -386,15 +366,15 @@ sys_net_wifi_entry WifiList::ToSTAEntry(const wifi_ap_record_t* ap) { } sys_net_wifi_entry& WifiList::ToSTAEntry( const wifi_sta_config_t* sta, sys_net_wifi_entry& item, const std::list& radio_types, sys_net_auth_types auth_type) { - if (!sta) { + if(!sta) { ESP_LOGE(TAG_CRED_MANAGER, "Invalid access point entry"); return item; } - + std::string ssid = GetSSID(sta); // Convert SSID to std::string std::string password = GetPassword(sta); // Convert password to std::string - if (ssid.empty()) { + if(ssid.empty()) { ESP_LOGE(TAG_CRED_MANAGER, "Invalid access point ssid"); return item; } @@ -402,7 +382,7 @@ sys_net_wifi_entry& WifiList::ToSTAEntry( memset(item.password, 0x00, sizeof(item.password)); strncpy(item.ssid, ssid.c_str(), sizeof(item.ssid)); // Copy SSID strncpy(item.password, password.c_str(), sizeof(item.password)); // Copy password - if (LOG_LOCAL_LEVEL > ESP_LOG_DEBUG) { + if(LOG_LOCAL_LEVEL > ESP_LOG_DEBUG) { WifiList::FormatBSSID(item.bssid, sizeof(item.bssid), sta->bssid); // Format BSSID } item.channel = sta->channel; @@ -410,16 +390,14 @@ sys_net_wifi_entry& WifiList::ToSTAEntry( item.auth_type = auth_type; // Handle the radio_type array - if (item.radio_type != nullptr) { + if(item.radio_type != nullptr) { delete[] item.radio_type; // Free existing array if any item.radio_type_count = 0; } item.radio_type_count = radio_types.size(); item.radio_type = new sys_net_radio_types[item.radio_type_count]; int i = 0; - for (const auto& type : radio_types) { - item.radio_type[i++] = type; - } + for(const auto& type : radio_types) { item.radio_type[i++] = type; } ESP_LOGV(TAG_CRED_MANAGER, "ToSTAEntry wifi : %s, password: %s", item.ssid, item.password); return item; @@ -427,7 +405,7 @@ sys_net_wifi_entry& WifiList::ToSTAEntry( bool WifiList::RemoveCredential(const wifi_sta_config_t* sta) { return RemoveCredential(GetSSID(sta)); } bool WifiList::RemoveCredential(const std::string& ssid) { auto it = credentials_.find(ssid); - if (it != credentials_.end()) { + if(it != credentials_.end()) { // Release any dynamically allocated fields in the structure Release(&it->second); // Erase the entry from the map @@ -438,51 +416,39 @@ bool WifiList::RemoveCredential(const std::string& ssid) { } void WifiList::Clear() { - if (Lock()) { - for (auto& e : credentials_) { - Release( &e.second); - } + if(Lock()) { + for(auto& e : credentials_) { Release(&e.second); } credentials_.clear(); Unlock(); } } bool WifiList::ResetRSSI() { - if (!Lock()) { + if(!Lock()) { ESP_LOGE(TAG_CRED_MANAGER, "Unable to lock structure %s", name_.c_str()); return false; } - for (auto& e : credentials_) { - e.second.rssi = 0; - } + for(auto& e : credentials_) { e.second.rssi = 0; } Unlock(); return true; } bool WifiList::ResetConnected() { - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } - for (auto& e : credentials_) { - e.second.connected = false; - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } + for(auto& e : credentials_) { e.second.connected = false; } Unlock(); return true; } sys_net_wifi_entry* WifiList::Get(const std::string& ssid) { auto it = credentials_.find(ssid); - if (it != credentials_.end()) { - return &(it->second); - } + if(it != credentials_.end()) { return &(it->second); } return nullptr; } const sys_net_wifi_entry* WifiList::GetConnected() { - if (!Lock()) { + if(!Lock()) { ESP_LOGE(TAG_CRED_MANAGER, "Unable to lock structure %s", name_.c_str()); return nullptr; } - for (auto& e : credentials_) { - if (e.second.connected) { - return &e.second; - } + for(auto& e : credentials_) { + if(e.second.connected) { return &e.second; } } Unlock(); return nullptr; @@ -491,13 +457,11 @@ bool WifiList::SetConnected(const wifi_event_sta_connected_t* evt, bool connecte auto ssid = GetSSID(evt); auto bssid = GetBSSID(evt); auto existing = Get(ssid); - if (existing) { - if (bssid != existing->bssid || existing->connected != connected || existing->auth_type != GetAuthType(evt->authmode) || + if(existing) { + if(bssid != existing->bssid || existing->connected != connected || existing->auth_type != GetAuthType(evt->authmode) || existing->channel != evt->channel) { ResetConnected(); - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } strncpy(existing->bssid, bssid.c_str(), sizeof(existing->bssid)); existing->connected = connected; existing->auth_type = GetAuthType(evt->authmode); @@ -512,21 +476,17 @@ bool WifiList::SetConnected(const wifi_event_sta_connected_t* evt, bool connecte return false; } - - sys_net_wifi_entry& WifiList::AddUpdate(const wifi_sta_config_t* sta, sys_net_auth_types auth_type) { return AddUpdate(sta, GetRadioTypes(nullptr), auth_type); } sys_net_wifi_entry& WifiList::AddUpdate( const wifi_sta_config_t* sta, const std::list& radio_types, sys_net_auth_types auth_type) { auto ssid = GetSSID(sta); - - if (!Exists(sta)) { + + if(!Exists(sta)) { auto entry = ToSTAEntry(sta, radio_types, auth_type); ESP_LOGD(TAG_CRED_MANAGER, "Added new entry %s to list %s", ssid.c_str(), name_.c_str()); - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } credentials_[ssid] = entry; Unlock(); } else { @@ -537,17 +497,13 @@ sys_net_wifi_entry& WifiList::AddUpdate( } bool WifiList::UpdateFromClock() { bool changed = false; - if (Lock()) { + if(Lock()) { - for (auto iter = credentials_.begin(); iter != credentials_.end(); ++iter) { + for(auto iter = credentials_.begin(); iter != credentials_.end(); ++iter) { bool entrychanged = false; - if (iter->second.has_last_seen) { - entrychanged |= OffsetTimeStamp(&iter->second.last_seen); - } - if (iter->second.has_last_try) { - entrychanged |= OffsetTimeStamp(&iter->second.last_try); - } - if (entrychanged) { + if(iter->second.has_last_seen) { entrychanged |= OffsetTimeStamp(&iter->second.last_seen); } + if(iter->second.has_last_try) { entrychanged |= OffsetTimeStamp(&iter->second.last_try); } + if(entrychanged) { ESP_LOGD(TAG_CRED_MANAGER, "Updated from clock"); PrintWifiSTAEntry(iter->second); } @@ -559,7 +515,7 @@ bool WifiList::UpdateFromClock() { return changed; } void WifiList::PrintTimeStamp(const google_protobuf_Timestamp* timestamp) { - if (timestamp == NULL) { + if(timestamp == NULL) { printf("Timestamp is NULL\n"); return; } @@ -567,14 +523,12 @@ void WifiList::PrintTimeStamp(const google_protobuf_Timestamp* timestamp) { char buffer[80]; // Check for special case of time == 0 - if (timestamp->seconds == 0) { - if (timestamp->nanos != 0) { - printf("nanos not empty!"); - } + if(timestamp->seconds == 0) { + if(timestamp->nanos != 0) { printf("nanos not empty!"); } snprintf(buffer, sizeof(buffer), "%-26s", "N/A"); } // Check for timestamps less than 1704143717 (2024-01-01) - else if (timestamp->seconds > 0 && timestamp->seconds < 1704143717) { + else if(timestamp->seconds > 0 && timestamp->seconds < 1704143717) { // Convert seconds to time_t for use with localtime time_t rawtime = (time_t)timestamp->seconds; struct tm* timeinfo = localtime(&rawtime); @@ -591,9 +545,7 @@ void WifiList::PrintTimeStamp(const google_protobuf_Timestamp* timestamp) { printf("%-26s", buffer); } bool WifiList::UpdateLastTry(const std::string ssid) { - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } auto entry = Get(ssid); ESP_RETURN_ON_FALSE(entry != nullptr, false, TAG_CRED_MANAGER, "Unknown ssid %s", ssid.c_str()); ESP_RETURN_ON_FALSE(entry->ssid != nullptr, false, TAG_CRED_MANAGER, "Invalid pointer!"); @@ -612,14 +564,10 @@ bool WifiList::UpdateLastTry(const wifi_ap_record_t* ap) { return UpdateLastTry( bool WifiList::UpdateLastSeen(const wifi_sta_config_t* sta) { return UpdateLastSeen(GetSSID(sta)); } bool WifiList::UpdateLastSeen(const wifi_ap_record_t* ap) { return UpdateLastSeen(GetSSID(ap)); } bool WifiList::UpdateLastSeen(const std::string ssid) { - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } auto entry = Get(ssid); bool changed = false; - if (entry != nullptr) { - changed = UpdateLastSeen(entry); - } + if(entry != nullptr) { changed = UpdateLastSeen(entry); } Unlock(); return changed; } @@ -630,11 +578,9 @@ bool WifiList::UpdateLastSeen(sys_net_wifi_entry* entry) { } sys_net_wifi_entry& WifiList::AddUpdate(const wifi_ap_record_t* scan_rec) { auto ssid = GetSSID(scan_rec); - if (!Exists(scan_rec)) { + if(!Exists(scan_rec)) { ESP_LOGV(TAG_CRED_MANAGER, "Added new entry %s to list %s", ssid.c_str(), name_.c_str()); - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } credentials_[ssid] = ToSTAEntry(scan_rec); Unlock(); } else { @@ -643,17 +589,13 @@ sys_net_wifi_entry& WifiList::AddUpdate(const wifi_ap_record_t* scan_rec) { return credentials_[ssid]; } sys_net_wifi_entry& WifiList::AddUpdate(const char* ssid, const char* password) { - if (ssid == nullptr || password == nullptr) { - throw std::invalid_argument("SSID and password cannot be null"); - } + if(ssid == nullptr || password == nullptr) { throw std::invalid_argument("SSID and password cannot be null"); } // Ensure that the SSID and password are not too long - if (std::strlen(ssid) >= sizeof(sys_net_wifi_entry::ssid) || std::strlen(password) >= sizeof(sys_net_wifi_entry::password)) { + if(std::strlen(ssid) >= sizeof(sys_net_wifi_entry::ssid) || std::strlen(password) >= sizeof(sys_net_wifi_entry::password)) { throw std::length_error("SSID or password is too long"); } - if (!Exists(ssid)) { - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Exists(ssid)) { + if(!Lock()) { throw std::runtime_error("Lock failed"); } sys_net_wifi_entry newEntry = sys_net_wifi_entry_init_default; // Copy the SSID and password into the new entry, ensuring null termination std::strncpy(newEntry.ssid, ssid, sizeof(newEntry.ssid) - 1); @@ -665,7 +607,7 @@ sys_net_wifi_entry& WifiList::AddUpdate(const char* ssid, const char* password) Unlock(); } else { auto existing = Get(ssid); - if (strncmp(existing->password, password, sizeof(existing->password)) != 0) { + if(strncmp(existing->password, password, sizeof(existing->password)) != 0) { strncpy(existing->password, password, sizeof(existing->password)); existing->password[sizeof(existing->password) - 1] = '\0'; } @@ -673,16 +615,12 @@ sys_net_wifi_entry& WifiList::AddUpdate(const char* ssid, const char* password) return credentials_[ssid]; } sys_net_wifi_entry& WifiList::AddUpdate(const sys_net_wifi_entry* sta, const char* password) { - if (sta == nullptr) { - throw std::invalid_argument("Entry pointer cannot be null"); - } + if(sta == nullptr) { throw std::invalid_argument("Entry pointer cannot be null"); } auto converted = ToSTAEntry(sta); - strncpy(converted.password, password, sizeof(converted.password)); - if (!Exists(sta->ssid)) { + strncpy(converted.password, password, sizeof(converted.password)); + if(!Exists(sta->ssid)) { ESP_LOGD(TAG_CRED_MANAGER, "Added new entry %s to list %s", sta->ssid, name_.c_str()); - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } credentials_[sta->ssid] = converted; Unlock(); } else { @@ -695,8 +633,8 @@ sys_net_wifi_entry& WifiList::AddUpdate(const sys_net_wifi_entry* sta, const cha } void WifiList::PrintString(const char* pData, size_t length, const char* format) { std::string buffer; - for (size_t i = 0; i < length && pData[i]; i++) { - if (isprint((char)pData[i])) { + for(size_t i = 0; i < length && pData[i]; i++) { + if(isprint((char)pData[i])) { buffer += (char)pData[i]; // Print as a character } else { buffer += '?'; @@ -723,12 +661,12 @@ void WifiList::PrintWifiSTAEntry(const sys_net_wifi_entry& entry) { printf("%3u ", static_cast(entry.channel)); printf("%-14s", sys_net_auth_types_name(entry.auth_type)); printf("%-9s", formatRadioTypes(entry.radio_type, entry.radio_type_count).c_str()); - if (entry.has_last_try) { + if(entry.has_last_try) { PrintTimeStamp(&entry.last_try); } else { PrintTimeStamp(>s); } - if (entry.has_last_seen) { + if(entry.has_last_seen) { PrintTimeStamp(&entry.last_seen); } else { PrintTimeStamp(>s); @@ -736,23 +674,17 @@ void WifiList::PrintWifiSTAEntry(const sys_net_wifi_entry& entry) { printf("\n"); } sys_net_wifi_entry* WifiList::GetIndex(size_t index) { - if (index >= credentials_.size()) { - return nullptr; - } + if(index >= credentials_.size()) { return nullptr; } auto it = credentials_.begin(); std::advance(it, index); return &(it->second); } sys_net_wifi_entry& WifiList::GetStrongestSTA() { - if (credentials_.empty()) { - throw std::runtime_error("No credentials available"); - } + if(credentials_.empty()) { throw std::runtime_error("No credentials available"); } auto strongestIter = credentials_.begin(); - for (auto iter = credentials_.begin(); iter != credentials_.end(); ++iter) { - if (iter->second.rssi > strongestIter->second.rssi) { - strongestIter = iter; - } + for(auto iter = credentials_.begin(); iter != credentials_.end(); ++iter) { + if(iter->second.rssi > strongestIter->second.rssi) { strongestIter = iter; } } return strongestIter->second; @@ -760,38 +692,24 @@ sys_net_wifi_entry& WifiList::GetStrongestSTA() { std::list WifiList::GetRadioTypes(const wifi_ap_record_t* sta) { std::list result; - if (sta == nullptr) { + if(sta == nullptr) { result.push_back(sys_net_radio_types_UNKNOWN); } else { // Check each bit field and return the corresponding enum value - if (sta->phy_11b) { - result.push_back(sys_net_radio_types_PHY_11B); - } - if (sta->phy_11g) { - result.push_back(sys_net_radio_types_PHY_11G); - } - if (sta->phy_11n) { - result.push_back(sys_net_radio_types_PHY_11N); - } - if (sta->phy_lr) { - result.push_back(sys_net_radio_types_LR); - } - if (sta->wps) { - result.push_back(sys_net_radio_types_WPS); - } - if (sta->ftm_responder) { - result.push_back(sys_net_radio_types_FTM_RESPONDER); - } - if (sta->ftm_initiator) { - result.push_back(sys_net_radio_types_FTM_INITIATOR); - } + if(sta->phy_11b) { result.push_back(sys_net_radio_types_PHY_11B); } + if(sta->phy_11g) { result.push_back(sys_net_radio_types_PHY_11G); } + if(sta->phy_11n) { result.push_back(sys_net_radio_types_PHY_11N); } + if(sta->phy_lr) { result.push_back(sys_net_radio_types_LR); } + if(sta->wps) { result.push_back(sys_net_radio_types_WPS); } + if(sta->ftm_responder) { result.push_back(sys_net_radio_types_FTM_RESPONDER); } + if(sta->ftm_initiator) { result.push_back(sys_net_radio_types_FTM_INITIATOR); } } return result; } wifi_auth_mode_t WifiList::GetESPAuthMode(sys_net_auth_types auth_type) { - switch (auth_type) { + switch(auth_type) { case sys_net_auth_types_OPEN: return WIFI_AUTH_OPEN; case sys_net_auth_types_WEP: @@ -814,12 +732,10 @@ wifi_auth_mode_t WifiList::GetESPAuthMode(sys_net_auth_types auth_type) { return WIFI_AUTH_OPEN; // Default case } } -sys_net_auth_types WifiList::GetAuthType(const wifi_ap_record_t* ap) { - return ap ? GetAuthType(ap->authmode) : sys_net_auth_types_AUTH_UNKNOWN; -} +sys_net_auth_types WifiList::GetAuthType(const wifi_ap_record_t* ap) { return ap ? GetAuthType(ap->authmode) : sys_net_auth_types_AUTH_UNKNOWN; } sys_net_auth_types WifiList::GetAuthType(const wifi_auth_mode_t mode) { - switch (mode) { + switch(mode) { case WIFI_AUTH_OPEN: return sys_net_auth_types_OPEN; case WIFI_AUTH_WEP: diff --git a/components/platform_config/WifiList.h b/components/platform_config/WifiList.h index ea8ffa89..dc92bc9d 100644 --- a/components/platform_config/WifiList.h +++ b/components/platform_config/WifiList.h @@ -38,9 +38,7 @@ class WifiList : public System::Locking { public: WifiList(std::string name) : System::Locking(name), name_(name) {} - ~WifiList(){ - Clear(); - } + ~WifiList() { Clear(); } static std::string toString(const uint8_t* data, size_t max_length) { // Find the actual length of the string up to max_length size_t length = strnlen(reinterpret_cast(data), max_length); @@ -48,25 +46,17 @@ class WifiList : public System::Locking { auto p = std::string(reinterpret_cast(data), length); return p; } - static void Release(sys_net_wifi_entry& entry){ - Release(&entry); - } - static void Release(sys_net_wifi_entry* entry){ - pb_release(&sys_net_wifi_entry_msg,entry); - } + static void Release(sys_net_wifi_entry& entry) { Release(&entry); } + static void Release(sys_net_wifi_entry* entry) { pb_release(&sys_net_wifi_entry_msg, entry); } static std::list GetRadioTypes(const wifi_ap_record_t* sta); static wifi_auth_mode_t GetESPAuthMode(sys_net_auth_types auth_type); static sys_net_auth_types GetAuthType(const wifi_ap_record_t* ap); static sys_net_auth_types GetAuthType(const wifi_auth_mode_t mode); static bool areRadioTypesDifferent(const sys_net_radio_types* types1, pb_size_t count1, const sys_net_radio_types* types2, pb_size_t count2) { - if (count1 != count2) { - return true; - } + if(count1 != count2) { return true; } - for (pb_size_t i = 0; i < count1; ++i) { - if (types1[i] != types2[i]) { - return true; - } + for(pb_size_t i = 0; i < count1; ++i) { + if(types1[i] != types2[i]) { return true; } } return false; @@ -80,12 +70,12 @@ class WifiList : public System::Locking { static std::string GetSSID(const wifi_sta_config_t* config) { return toString(config->ssid, sizeof(config->ssid)); } static std::string GetSSID(const wifi_ap_record_t* ap) { return toString(ap->ssid, sizeof(ap->ssid)); } static void FormatBSSID(char* buffer, size_t len, const uint8_t* bssid) { - memset(buffer,0x00,len); + memset(buffer, 0x00, len); snprintf(buffer, len, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); } static void FormatBSSID(const wifi_ap_record_t* ap, sys_net_wifi_entry& entry) { - memset(entry.bssid,0x00,sizeof(entry.bssid)); - if (!ap) return; + memset(entry.bssid, 0x00, sizeof(entry.bssid)); + if(!ap) return; FormatBSSID(entry.bssid, sizeof(entry.bssid), ap->bssid); } static std::string GetBSSID(const wifi_event_sta_connected_t* evt); @@ -111,7 +101,7 @@ class WifiList : public System::Locking { static void PrintWifiSTAEntry(const sys_net_wifi_entry& entry); static std::string formatRadioTypes(const sys_net_radio_types* radioTypes, pb_size_t count); - static bool OffsetTimeStamp(google_protobuf_Timestamp * ts); + static bool OffsetTimeStamp(google_protobuf_Timestamp* ts); static bool UpdateTimeStamp(google_protobuf_Timestamp* ts, bool& has_flag_val); bool ResetRSSI(); @@ -153,9 +143,7 @@ class WifiList : public System::Locking { sys_net_wifi_entry& AddUpdate(const sys_net_wifi_entry* existing, const char* password = ""); // this one below is used by pb_decode void AddUpdate(const sys_net_wifi_entry& entry) { - if (!Lock()) { - throw std::runtime_error("Lock failed"); - } + if(!Lock()) { throw std::runtime_error("Lock failed"); } credentials_[entry.ssid] = entry; Unlock(); } diff --git a/components/platform_config/test/test_platform_config.cpp b/components/platform_config/test/test_platform_config.cpp index 7b17dec5..1dcb95f3 100644 --- a/components/platform_config/test/test_platform_config.cpp +++ b/components/platform_config/test/test_platform_config.cpp @@ -43,7 +43,7 @@ bool HasMemoryUsageIncreased(int round) { static size_t initialFreeSPIRAM = 0; auto minFreeInternal = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); auto minFreeSPIRAM = heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); - if (round > 0) { + if(round > 0) { postTestFreeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); postTestFreeSPIRAM = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); minFreeInternal = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); @@ -56,7 +56,7 @@ bool HasMemoryUsageIncreased(int round) { postTestFreeSPIRAM, minFreeSPIRAM, initialFreeSPIRAM - postTestFreeSPIRAM); int32_t diffInternal = initialFreeInternal > postTestFreeInternal ? initialFreeInternal - postTestFreeInternal : 0; int32_t diffSPIRAM = initialFreeSPIRAM > postTestFreeSPIRAM ? initialFreeSPIRAM - postTestFreeSPIRAM : 0; - if (diffSPIRAM > 0 || diffInternal > 0) { + if(diffSPIRAM > 0 || diffInternal > 0) { ESP_LOGW(TAG, "Internal increase: %d, SPIRAM: %d", diffInternal, diffSPIRAM); return true; } @@ -147,24 +147,24 @@ sys_net_wifi_entry getMockEntry(int i = 0) { return mock; } -void FillSSIDs(WifiList& manager, int count, int start=1) { - for (int i = start; i <= count; i++) { +void FillSSIDs(WifiList& manager, int count, int start = 1) { + for(int i = start; i <= count; i++) { auto mock = getMockSTA(i); auto& entry = manager.AddUpdate(&mock); entry.rssi = 70 + i; entry.connected = true; } } -void FillSSIDFromAPRec(WifiList& manager, int count, int start=1) { - for (int i = start; i <= count; i++) { +void FillSSIDFromAPRec(WifiList& manager, int count, int start = 1) { + for(int i = start; i <= count; i++) { auto mock = getMockAPRec(i); auto& entry = manager.AddUpdate(&mock); entry.rssi = 70 + i; entry.connected = true; } } -void FillSSIDFromMockEntry(WifiList& manager, int count, int start=1) { - for (int i = start; i <= count; i++) { +void FillSSIDFromMockEntry(WifiList& manager, int count, int start = 1) { + for(int i = start; i <= count; i++) { auto mock = getMockEntry(i); auto& entry = manager.AddUpdate(&mock); entry.rssi = 70 + i; @@ -238,9 +238,7 @@ const sys_config* GetTestConfig() { test_config.dev.rotary.longpress = true; test_config.has_names = true; strcpy(test_config.names.device, "test_name"); - if (!test_config.target) { - test_config.target = strdup_psram("test_target"); - } + if(!test_config.target) { test_config.target = strdup_psram("test_target"); } return &test_config; } void check_sys_config_structure(sys_config* config) { @@ -674,19 +672,19 @@ TEST_CASE("Remove entries from manager instance", "[WifiCredentialsManager]") { TEST_CASE("Reset all entries", "[WifiCredentialsManager]") { WifiCredentialsManager manager("test_manager"); FillSSIDs(manager, 4); - for (auto& e : manager) { + for(auto& e : manager) { TEST_ASSERT_TRUE(e.second.rssi > 0); TEST_ASSERT_TRUE(e.second.connected); } manager.ResetRSSI(); - for (auto& e : manager) { + for(auto& e : manager) { TEST_ASSERT_TRUE(e.second.rssi == 0); TEST_ASSERT_TRUE(e.second.connected); } manager.Clear(); FillSSIDs(manager, 4); manager.ResetConnected(); - for (auto& e : manager) { + for(auto& e : manager) { TEST_ASSERT_TRUE(e.second.rssi > 0); TEST_ASSERT_FALSE(e.second.connected); } @@ -699,10 +697,8 @@ TEST_CASE("Getting/setting Connected", "[WifiCredentialsManager]") { auto entry_5 = getMockEntry(5); char bssid_buffer[20] = {}; FillSSIDs(manager, 4); - for (auto& e : manager) { - if (strcmp(e.second.ssid, "SSID_3") != 0) { - e.second.connected = false; - } + for(auto& e : manager) { + if(strcmp(e.second.ssid, "SSID_3") != 0) { e.second.connected = false; } } auto entry = manager.GetConnected(); TEST_ASSERT_EQUAL_STRING("SSID_3", entry->ssid); @@ -732,7 +728,7 @@ TEST_CASE("Getting by index/by name", "[WifiCredentialsManager]") { char buffer[25] = {}; WifiCredentialsManager manager("test_manager"); FillSSIDs(manager, 4); - for (int i = 0; i < manager.GetCount(); i++) { + for(int i = 0; i < manager.GetCount(); i++) { sprintf(buffer, "SSID_%d", i + 1); auto mockap = getMockAPRec(i + 1); auto mockSTA = getMockSTA(i + 1); @@ -763,7 +759,7 @@ TEST_CASE("Update last try", "[WifiCredentialsManager]") { WifiList manager("test_manager"); FillSSIDs(manager, 4); - for (int i = 0; i < manager.GetCount(); i++) { + for(int i = 0; i < manager.GetCount(); i++) { sprintf(buffer, "SSID_%d", i + 1); auto mockap = getMockAPRec(i + 1); auto mockSTA = getMockSTA(i + 1); @@ -806,7 +802,7 @@ TEST_CASE("Update last seen", "[WifiCredentialsManager]") { WifiList manager("test_manager"); FillSSIDs(manager, 4); - for (int i = 0; i < manager.GetCount(); i++) { + for(int i = 0; i < manager.GetCount(); i++) { sprintf(buffer, "SSID_%d", i + 1); auto mockap = getMockAPRec(i + 1); auto mockSTA = getMockSTA(i + 1); @@ -840,7 +836,7 @@ TEST_CASE("Update last seen", "[WifiCredentialsManager]") { TEST_CASE("Memory leak test", "[WifiCredentialsManager]") { char buffer[25] = {}; char err_buffer[55] = {}; - int fillqty=20; + int fillqty = 20; google_protobuf_Timestamp ts; bool flag; @@ -850,16 +846,16 @@ TEST_CASE("Memory leak test", "[WifiCredentialsManager]") { advanceTime(2); HasMemoryUsageIncreased(0); - for (int runs = 0; runs < 100; runs++) { + for(int runs = 0; runs < 100; runs++) { WifiCredentialsManager manager("test_manager"); FillSSIDs(manager, fillqty); - for (int i = 1; i <= manager.GetCount(); i++) { + for(int i = 1; i <= manager.GetCount(); i++) { sprintf(buffer, "SSID_%d", i); - sprintf(err_buffer,"Round %d, SSID_%d",runs,i); + sprintf(err_buffer, "Round %d, SSID_%d", runs, i); auto mockap = getMockAPRec(i); auto mockSTA = getMockSTA(i); auto entry = manager.Get(buffer); - TEST_ASSERT_EQUAL_STRING(buffer,entry->ssid); + TEST_ASSERT_EQUAL_STRING(buffer, entry->ssid); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(entry); @@ -868,86 +864,86 @@ TEST_CASE("Memory leak test", "[WifiCredentialsManager]") { entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(std::string(buffer)); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(&mockap); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(&mockSTA); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); } manager.Clear(); } TEST_ASSERT_FALSE(HasMemoryUsageIncreased(1)); - for (int runs = 0; runs < 100; runs++) { + for(int runs = 0; runs < 100; runs++) { WifiCredentialsManager manager("test_manager"); FillSSIDFromAPRec(manager, fillqty); - for (int i = 1; i <= manager.GetCount(); i++) { + for(int i = 1; i <= manager.GetCount(); i++) { sprintf(buffer, "SSID_%d", i); - sprintf(err_buffer,"Round %d, SSID_%d",runs,i); + sprintf(err_buffer, "Round %d, SSID_%d", runs, i); auto mockap = getMockAPRec(i); auto mockSTA = getMockSTA(i); - auto entry = manager.GetIndex(i-1); + auto entry = manager.GetIndex(i - 1); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(entry); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(std::string(buffer)); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(&mockap); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(&mockSTA); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); } manager.Clear(); } TEST_ASSERT_FALSE(HasMemoryUsageIncreased(2)); - for (int runs = 0; runs < 100; runs++) { + for(int runs = 0; runs < 100; runs++) { WifiCredentialsManager manager("test_manager"); FillSSIDFromMockEntry(manager, fillqty); - for (int i = 1; i <= manager.GetCount(); i++) { + for(int i = 1; i <= manager.GetCount(); i++) { sprintf(buffer, "SSID_%d", i); - sprintf(err_buffer,"Round %d, SSID_%d",runs,i); + sprintf(err_buffer, "Round %d, SSID_%d", runs, i); auto mockap = getMockAPRec(i); auto mockSTA = getMockSTA(i); - auto entry = manager.GetIndex(i-1); + auto entry = manager.GetIndex(i - 1); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(entry); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(std::string(buffer)); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(&mockap); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); entry->has_last_seen = false; memset(&entry->last_seen, 0x00, sizeof(entry->last_seen)); manager.UpdateLastSeen(&mockSTA); - TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen,err_buffer); - TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds,err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->has_last_seen, err_buffer); + TEST_ASSERT_TRUE_MESSAGE(entry->last_seen.seconds >= ts.seconds, err_buffer); } manager.Clear(); } diff --git a/components/platform_console/app_recovery/recovery.c b/components/platform_console/app_recovery/recovery.c index 63161269..1b1d19b7 100644 --- a/components/platform_console/app_recovery/recovery.c +++ b/components/platform_console/app_recovery/recovery.c @@ -6,8 +6,8 @@ #include "esp_app_desc.h" #include "cJSON.h" #include "stdbool.h" -extern esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length); -extern cJSON * gpio_list; +extern esp_err_t process_recovery_ota(const char* bin_url, char* bin_buffer, uint32_t length); +extern cJSON* gpio_list; const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { .magic_word = ESP_APP_DESC_MAGIC_WORD, .version = PROJECT_VER, @@ -28,35 +28,23 @@ const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = { .date = "", #endif }; -cJSON * get_gpio_list(bool refresh){ - if(!gpio_list){ - gpio_list = cJSON_CreateArray(); - } +cJSON* get_gpio_list(bool refresh) { + if(!gpio_list) { gpio_list = cJSON_CreateArray(); } return gpio_list; } -void register_optional_cmd(void) { -} +void register_optional_cmd(void) {} -int main(int argc, char **argv){ - return 1; -} +int main(int argc, char** argv) { return 1; } // void register_squeezelite(){ // } -void start_squeezelite(){ -} +void start_squeezelite() {} -void register_external(void) { -} +void register_external(void) {} -void deregister_external(void) { -} +void deregister_external(void) {} -void decode_restore(int external) { -} +void decode_restore(int external) {} -esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length) -{ - return process_recovery_ota(bin_url,bin_buffer,length); -} +esp_err_t start_ota(const char* bin_url, char* bin_buffer, uint32_t length) { return process_recovery_ota(bin_url, bin_buffer, length); } diff --git a/components/platform_console/app_squeezelite/cmd_squeezelite.c b/components/platform_console/app_squeezelite/cmd_squeezelite.c index d4a158ec..b2cefe8d 100644 --- a/components/platform_console/app_squeezelite/cmd_squeezelite.c +++ b/components/platform_console/app_squeezelite/cmd_squeezelite.c @@ -19,7 +19,6 @@ extern esp_err_t process_recovery_ota(const char* bin_url, char* bin_buffer, uin extern int squeezelite_main_start(); extern sys_dac_default_sets* default_dac_sets; - static const char* TAG = "squeezelite_cmd"; #define SQUEEZELITE_THREAD_STACK_SIZE (8 * 1024) #define ADDITIONAL_SQUEEZELITE_ARGS 5 @@ -75,42 +74,36 @@ static void squeezelite_thread(void* arg) { int wait = 60; int ret = squeezelite_main_start(); - if (ret == -2) { - cmd_send_messaging("cfg-audio-tmpl", MESSAGING_ERROR, - "Squeezelite not configured. Rebooting to factory in %d sec\n", wait); + if(ret == -2) { + cmd_send_messaging("cfg-audio-tmpl", MESSAGING_ERROR, "Squeezelite not configured. Rebooting to factory in %d sec\n", wait); vTaskDelay(pdMS_TO_TICKS(wait * 1000)); guided_factory(); } else { - cmd_send_messaging("cfg-audio-tmpl", ret > 1 ? MESSAGING_ERROR : MESSAGING_WARNING, - "squeezelite exited with error code %d\n", ret); - if (ret <= 1) { + cmd_send_messaging("cfg-audio-tmpl", ret > 1 ? MESSAGING_ERROR : MESSAGING_WARNING, "squeezelite exited with error code %d\n", ret); + if(ret <= 1) { - cmd_send_messaging( - "cfg-audio-tmpl", MESSAGING_ERROR, "Rebooting to factory in %d sec\n", wait); + cmd_send_messaging("cfg-audio-tmpl", MESSAGING_ERROR, "Rebooting to factory in %d sec\n", wait); vTaskDelay(pdMS_TO_TICKS(wait * 1000)); guided_factory(); } else { - cmd_send_messaging( - "cfg-audio-tmpl", MESSAGING_ERROR, "Correct command line and reboot\n"); + cmd_send_messaging("cfg-audio-tmpl", MESSAGING_ERROR, "Correct command line and reboot\n"); vTaskSuspend(NULL); } } ESP_LOGV(TAG, "Exited from squeezelite's main(). Freeing argv structure."); - for (int i = 0; i < thread_parms.argc; i++) - free(thread_parms.argv[i]); + for(int i = 0; i < thread_parms.argc; i++) free(thread_parms.argv[i]); free(thread_parms.argv); } static int launchsqueezelite(int argc, char** argv) { static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__((aligned(4))); - static EXT_RAM_ATTR StackType_t xStack[SQUEEZELITE_THREAD_STACK_SIZE] - __attribute__((aligned(4))); + static EXT_RAM_ATTR StackType_t xStack[SQUEEZELITE_THREAD_STACK_SIZE] __attribute__((aligned(4))); static bool isRunning = false; - if (isRunning) { + if(isRunning) { ESP_LOGE(TAG, "Squeezelite already running. Exiting!"); return -1; } @@ -118,14 +111,13 @@ static int launchsqueezelite(int argc, char** argv) { ESP_LOGV(TAG, "Begin"); isRunning = true; - // load the presets here, as the squeezelite cannot access the + // load the presets here, as the squeezelite cannot access the // spiffs storage // proto_load_file("/spiffs/presets/default_sets.bin", &sys_dac_default_sets_msg, default_dac_sets, false); ESP_LOGD(TAG, "Starting Squeezelite Thread"); - xTaskCreateStaticPinnedToCore(squeezelite_thread, "squeezelite", SQUEEZELITE_THREAD_STACK_SIZE, - NULL, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT, xStack, &xTaskBuffer, - CONFIG_PTHREAD_TASK_CORE_DEFAULT); + xTaskCreateStaticPinnedToCore(squeezelite_thread, "squeezelite", SQUEEZELITE_THREAD_STACK_SIZE, NULL, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT, + xStack, &xTaskBuffer, CONFIG_PTHREAD_TASK_CORE_DEFAULT); return 0; } @@ -142,7 +134,7 @@ void start_squeezelite() { launchsqueezelite(0, NULL); } // } esp_err_t start_ota(const char* bin_url, char* bin_buffer, uint32_t length) { - if (!bin_url || strlen(bin_url) == 0) { + if(!bin_url || strlen(bin_url) == 0) { ESP_LOGE(TAG, "missing URL parameter. Unable to start OTA"); return ESP_ERR_INVALID_ARG; } @@ -150,9 +142,7 @@ esp_err_t start_ota(const char* bin_url, char* bin_buffer, uint32_t length) { system_set_string(&sys_state_data_msg, sys_state_data_ota_url_tag, sys_state, bin_url); config_raise_state_changed(); - if (!config_waitcommit()) { - ESP_LOGW(TAG, "Unable to commit configuration. "); - } + if(!config_waitcommit()) { ESP_LOGW(TAG, "Unable to commit configuration. "); } ESP_LOGW(TAG, "Rebooting to recovery to complete the installation"); return guided_factory(); return ESP_OK; diff --git a/components/platform_console/cmd_config.c b/components/platform_console/cmd_config.c index f23f6eba..9658dc2f 100644 --- a/components/platform_console/cmd_config.c +++ b/components/platform_console/cmd_config.c @@ -216,12 +216,12 @@ int is_gpio(struct arg_int* gpio, FILE* f, int* gpio_out, bool mandatory, bool o const char* name = gpio->hdr.longopts ? gpio->hdr.longopts : gpio->hdr.glossary; *gpio_out = -1; int t_gpio = gpio->ival[0]; - if (gpio->count == 0) { - if (mandatory) { + if(gpio->count == 0) { + if(mandatory) { fprintf(f, "Missing: %s\n", name); res++; } - } else if ((output && !GPIO_IS_VALID_OUTPUT_GPIO(t_gpio)) || (!GPIO_IS_VALID_GPIO(t_gpio))) { + } else if((output && !GPIO_IS_VALID_OUTPUT_GPIO(t_gpio)) || (!GPIO_IS_VALID_GPIO(t_gpio))) { fprintf(f, "Invalid %s gpio: [%d] %s\n", name, t_gpio, GPIO_IS_VALID_GPIO(t_gpio) ? NOT_OUTPUT : NOT_GPIO); res++; } else { @@ -233,14 +233,14 @@ int is_output_gpio(struct arg_int* gpio, FILE* f, int* gpio_out, bool mandatory) int check_missing_parm(struct arg_int* int_parm, FILE* f) { int res = 0; const char* name = int_parm->hdr.longopts ? int_parm->hdr.longopts : int_parm->hdr.glossary; - if (int_parm->count == 0) { + if(int_parm->count == 0) { fprintf(f, "Missing: %s\n", name); res++; } return res; } char* strip_bt_name(char* opt_str) { - if (!opt_str || strlen(opt_str) == 0) { + if(!opt_str || strlen(opt_str) == 0) { ESP_LOGW(TAG, "strip_bt_name: opt_str is NULL"); return NULL; } @@ -248,27 +248,27 @@ char* strip_bt_name(char* opt_str) { char* str = strdup_psram(opt_str); const char* output_marker = " -o"; - if (!result) { + if(!result) { ESP_LOGE(TAG, "Error allocating memory for result."); return opt_str; } - if (!str) { + if(!str) { ESP_LOGE(TAG, "Error duplicating command line string."); return opt_str; } bool quoted = false; parse_state_t state = SEARCHING_FOR_BT; char* start = strstr(str, output_marker); - if (start) { + if(start) { ESP_LOGV(TAG, "Found output option : %s\n", start); start += strlen(output_marker); strncpy(result, str, (size_t)(start - str)); char* pch = strtok(start, " "); - while (pch) { + while(pch) { ESP_LOGV(TAG, "Current output: %s\n[%s]", result, pch); - switch (state) { + switch(state) { case SEARCHING_FOR_BT: - if (strcasestr(pch, "BT")) { + if(strcasestr(pch, "BT")) { state = SEARCHING_FOR_NAME; quoted = strcasestr(pch, "BT") != NULL; ESP_LOGV(TAG, " - fount BT Start %s", quoted ? "quoted" : ""); @@ -279,7 +279,7 @@ char* strip_bt_name(char* opt_str) { strcat(result, pch); break; case SEARCHING_FOR_NAME: - if (strcasestr(pch, "name") || strcasestr(pch, "n")) { + if(strcasestr(pch, "name") || strcasestr(pch, "n")) { ESP_LOGV(TAG, " - Found name tag"); state = SEARCHING_FOR_NAME_START; } else { @@ -294,10 +294,10 @@ char* strip_bt_name(char* opt_str) { state = SEARCHING_FOR_NAME_END; break; case SEARCHING_FOR_NAME_END: - if (strcasestr(pch, "\"")) { + if(strcasestr(pch, "\"")) { ESP_LOGV(TAG, " - got quoted string"); state = FINISHING; - } else if (pch[0] == '-') { + } else if(pch[0] == '-') { strcat(result, " "); strcat(result, pch); ESP_LOGV(TAG, " - got parameter marker"); @@ -308,7 +308,7 @@ char* strip_bt_name(char* opt_str) { break; case SEARCHING_FOR_BT_CMD_END: ESP_LOGV(TAG, " - looking for quoted BT cmd end"); - if (strcasestr(pch, "\"")) { + if(strcasestr(pch, "\"")) { ESP_LOGV(TAG, " - got quote termination"); state = FINISHING; } @@ -343,16 +343,14 @@ static int do_bt_source_cmd(int argc, char** argv) { size_t buf_size = 0; // char value[100] ={0}; FILE* f = system_open_memstream(argv[0], &buf, &buf_size); - if (f == NULL) { - return 1; - } - if (nerrors > 0) { + if(f == NULL) { return 1; } + if(nerrors > 0) { arg_print_errors(f, bt_source_args.end, desc_bt_source); fclose(f); return 1; } - if (bt_source_args.sink_name->count > 0) { + if(bt_source_args.sink_name->count > 0) { // err = config_set_value(NVS_TYPE_STR, "a2dp_sink_name", bt_source_args.sink_name->sval[0]); // if(err!=ESP_OK){ // nerrors++; @@ -378,15 +376,13 @@ static int do_bt_source_cmd(int argc, char** argv) { // } // TODO: Add support for the commented code } - if (bt_source_args.pin_code->count > 0) { + if(bt_source_args.pin_code->count > 0) { const char* v = bt_source_args.pin_code->sval[0]; bool bInvalid = false; - for (int i = 0; i < strlen(v) && !bInvalid; i++) { - if (v[i] < '0' || v[i] > '9') { - bInvalid = true; - } + for(int i = 0; i < strlen(v) && !bInvalid; i++) { + if(v[i] < '0' || v[i] > '9') { bInvalid = true; } } - if (bInvalid || strlen(bt_source_args.pin_code->sval[0]) > 16 || strlen(bt_source_args.pin_code->sval[0]) < 4) { + if(bInvalid || strlen(bt_source_args.pin_code->sval[0]) > 16 || strlen(bt_source_args.pin_code->sval[0]) < 4) { nerrors++; fprintf(f, "Pin code %s invalid. Should be numbers only with length between 4 and 16 characters. \n", bt_source_args.pin_code->sval[0]); } else { @@ -442,9 +438,7 @@ static int do_bt_source_cmd(int argc, char** argv) { // } // } - if (!nerrors) { - fprintf(f, "Done.\n"); - } + if(!nerrors) { fprintf(f, "Done.\n"); } fflush(f); cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); fclose(f); @@ -453,34 +447,28 @@ static int do_bt_source_cmd(int argc, char** argv) { } static int do_wifi_join(int argc, char** argv) { int nerrors = arg_parse(argc, argv, (void**)&wifi_join_args); - if (nerrors > 0) { - return 1; - } + if(nerrors > 0) { return 1; } - network_async_connect(wifi_join_args.ap_name->sval[0], wifi_join_args.password->count > 0 ? wifi_join_args.password->sval[0] : ""); + network_async_connect(wifi_join_args.ap_name->sval[0], wifi_join_args.password->count > 0 ? wifi_join_args.password->sval[0] : ""); return 0; } static int do_wifi_add(int argc, char** argv) { int nerrors = arg_parse(argc, argv, (void**)&wifi_join_args); - if (nerrors > 0) { - return 1; - } + if(nerrors > 0) { return 1; } - network_async_add(wifi_join_args.ap_name->sval[0], wifi_join_args.password->count > 0 ? wifi_join_args.password->sval[0] : ""); + network_async_add(wifi_join_args.ap_name->sval[0], wifi_join_args.password->count > 0 ? wifi_join_args.password->sval[0] : ""); return 0; } static int do_wifi_delete(int argc, char** argv) { int nerrors = arg_parse(argc, argv, (void**)&wifi_delete_args); - if (nerrors > 0) { - return 1; - } - network_async_delete_connection(wifi_delete_args.ap_name->sval[0]); + if(nerrors > 0) { return 1; } + network_async_delete_connection(wifi_delete_args.ap_name->sval[0]); return 0; } // Function to handle WiFi scan static int do_wifi_scan(int argc, char** argv) { - int nerrors = arg_parse(argc, argv, (void**) &wifi_scan_args); - if (nerrors > 0) { + int nerrors = arg_parse(argc, argv, (void**)&wifi_scan_args); + if(nerrors > 0) { arg_print_errors(stderr, wifi_scan_args.end, argv[0]); return 1; } @@ -490,8 +478,8 @@ static int do_wifi_scan(int argc, char** argv) { // Function to handle WiFi status static int do_wifi_status(int argc, char** argv) { - int nerrors = arg_parse(argc, argv, (void**) &wifi_status_args); - if (nerrors > 0) { + int nerrors = arg_parse(argc, argv, (void**)&wifi_status_args); + if(nerrors > 0) { arg_print_errors(stderr, wifi_status_args.end, argv[0]); return 1; } @@ -501,8 +489,8 @@ static int do_wifi_status(int argc, char** argv) { // Function to handle WiFi reset static int do_wifi_reset(int argc, char** argv) { - int nerrors = arg_parse(argc, argv, (void**) &wifi_reset_args); - if (nerrors > 0) { + int nerrors = arg_parse(argc, argv, (void**)&wifi_reset_args); + if(nerrors > 0) { arg_print_errors(stderr, wifi_reset_args.end, argv[0]); return 1; } @@ -511,17 +499,14 @@ static int do_wifi_reset(int argc, char** argv) { return 0; } - static int do_audio_cmd(int argc, char** argv) { esp_err_t err = ESP_OK; int nerrors = arg_parse(argc, argv, (void**)&audio_args); char* buf = NULL; size_t buf_size = 0; FILE* f = system_open_memstream(argv[0], &buf, &buf_size); - if (f == NULL) { - return 1; - } - if (nerrors > 0) { + if(f == NULL) { return 1; } + if(nerrors > 0) { arg_print_errors(f, audio_args.end, desc_audio); fclose(f); return 1; @@ -529,10 +514,10 @@ static int do_audio_cmd(int argc, char** argv) { err = ESP_OK; // suppress any error code that might have happened in a previous step - if (audio_args.loudness->count > 0) { + if(audio_args.loudness->count > 0) { char p[4] = {0}; int loudness_val = audio_args.loudness->ival[0]; - if (loudness_val < 0 || loudness_val > 10) { + if(loudness_val < 0 || loudness_val > 10) { nerrors++; fprintf(f, "Invalid loudness value %d. Valid values are between 0 and 10.\n", loudness_val); } @@ -542,7 +527,7 @@ static int do_audio_cmd(int argc, char** argv) { // err = config_set_value(NVS_TYPE_STR, "loudness", p); // TODO: Add support for the commented code } - if (err != ESP_OK) { + if(err != ESP_OK) { nerrors++; fprintf(f, "Error setting Loudness value %s. %s\n", p, esp_err_to_name(err)); } else { @@ -551,7 +536,7 @@ static int do_audio_cmd(int argc, char** argv) { } } - if (audio_args.jack_behavior->count > 0) { + if(audio_args.jack_behavior->count > 0) { err = ESP_OK; // suppress any error code that might have happened in a previous step // TODO: Add support for the commented code // if(strcasecmp(audio_args.jack_behavior->sval[0],"Headphones")==0){ @@ -565,7 +550,7 @@ static int do_audio_cmd(int argc, char** argv) { // fprintf(f,"Unknown Audio Jack Behavior %s.\n",audio_args.jack_behavior->sval[0]); // } - if (err != ESP_OK) { + if(err != ESP_OK) { nerrors++; fprintf(f, "Error setting Audio Jack Behavior %s. %s\n", audio_args.jack_behavior->sval[0], esp_err_to_name(err)); } else { @@ -573,9 +558,7 @@ static int do_audio_cmd(int argc, char** argv) { } } - if (!nerrors) { - fprintf(f, "Done.\n"); - } + if(!nerrors) { fprintf(f, "Done.\n"); } fflush(f); cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); fclose(f); @@ -695,11 +678,11 @@ static int do_audio_cmd(int argc, char** argv) { // } static int is_valid_gpio_number(int gpio, const char* name, FILE* f, bool mandatory, struct arg_int* target, bool output) { bool invalid = (!GPIO_IS_VALID_GPIO(gpio) || (output && !GPIO_IS_VALID_OUTPUT_GPIO(gpio))); - if (invalid && mandatory && gpio != -1) { + if(invalid && mandatory && gpio != -1) { fprintf(f, "Error: Invalid mandatory gpio %d for %s\n", gpio, name); return 1; } - if (target && !invalid) { + if(target && !invalid) { target->count = 1; target->ival[0] = gpio; } @@ -709,16 +692,12 @@ static int is_valid_gpio_number(int gpio, const char* name, FILE* f, bool mandat #ifdef CONFIG_CSPOT_SINK static int do_cspot_config(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&cspot_args); - if (nerrors != 0) { - return 1; - } + if(nerrors != 0) { return 1; } char* buf = NULL; size_t buf_size = 0; FILE* f = system_open_memstream(argv[0], &buf, &buf_size); - if (f == NULL) { - return 1; - } + if(f == NULL) { return 1; } // cJSON * cspot_config = config_alloc_get_cjson("cspot_config"); // if(!cspot_config){ @@ -914,7 +893,7 @@ cJSON* known_model_cb() { #ifdef CONFIG_CSPOT_SINK cJSON* cspot_cb() { cJSON* values = cJSON_CreateObject(); - if (!values) { + if(!values) { ESP_LOGE(TAG, "cspot_cb: Failed to create JSON object"); return NULL; } @@ -1087,15 +1066,11 @@ cJSON* bt_source_cb() { void get_str_parm_json(struct arg_str* parm, cJSON* entry) { const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; - if (parm->count > 0) { - cJSON_AddStringToObject(entry, name, parm->sval[0]); - } + if(parm->count > 0) { cJSON_AddStringToObject(entry, name, parm->sval[0]); } } void get_file_parm_json(struct arg_file* parm, cJSON* entry) { const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; - if (parm->count > 0) { - cJSON_AddStringToObject(entry, name, parm->filename[0]); - } + if(parm->count > 0) { cJSON_AddStringToObject(entry, name, parm->filename[0]); } } void get_lit_parm_json(struct arg_lit* parm, cJSON* entry) { const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; @@ -1103,9 +1078,7 @@ void get_lit_parm_json(struct arg_lit* parm, cJSON* entry) { } void get_int_parm_json(struct arg_int* parm, cJSON* entry) { const char* name = parm->hdr.longopts ? parm->hdr.longopts : parm->hdr.glossary; - if (parm->count > 0) { - cJSON_AddNumberToObject(entry, name, parm->ival[0]); - } + if(parm->count > 0) { cJSON_AddNumberToObject(entry, name, parm->ival[0]); } } static int do_squeezelite_cmd(int argc, char** argv) { @@ -1114,9 +1087,7 @@ static int do_squeezelite_cmd(int argc, char** argv) { char* buf = NULL; size_t buf_size = 0; FILE* f = system_open_memstream(argv[0], &buf, &buf_size); - if (f == NULL) { - return 1; - } + if(f == NULL) { return 1; } fprintf(f, "Not yet implemented!"); nerrors += 1; fflush(f); @@ -1198,7 +1169,7 @@ static char* get_log_level_options(const char* longname) { const char* template = "<%s=info|%s=debug|%s=sdebug>"; char* options = NULL; int len = snprintf(NULL, 0, template, longname, longname, longname); - if (len > 0) { + if(len > 0) { options = malloc_init_external(len + 1); snprintf(options, len, template, longname, longname, longname); } @@ -1235,10 +1206,8 @@ static char* get_log_level_options(const char* longname) { // return dac_list; // } void replace_char_in_string(char* str, char find, char replace) { - for (int i = 0; str[i]; i++) { - if (str[i] == find) { - str[i] = replace; - } + for(int i = 0; str[i]; i++) { + if(str[i] == find) { str[i] = replace; } } } static esp_err_t save_known_config(cJSON* known_item, const char* name, FILE* f) { @@ -1249,20 +1218,20 @@ static esp_err_t save_known_config(cJSON* known_item, const char* name, FILE* f) FREE_AND_NULL(json_string); cJSON* kvp = NULL; cJSON* config_array = cJSON_GetObjectItem(known_item, "config"); - if (config_array && cJSON_IsArray(config_array)) { + if(config_array && cJSON_IsArray(config_array)) { json_string = cJSON_Print(config_array); ESP_LOGD(TAG, "config_array: %s", STR_OR_BLANK(json_string)); FREE_AND_NULL(json_string); cJSON_ArrayForEach(kvp, config_array) { cJSON* kvp_value = kvp->child; - if (!kvp_value) { + if(!kvp_value) { printf("config entry is not an object!\n"); err = ESP_FAIL; continue; } char* key = kvp_value->string; char* value = kvp_value->valuestring; - if (!key || !value || strlen(key) == 0) { + if(!key || !value || strlen(key) == 0) { printf("Invalid config entry %s:%s\n", STR_OR_BLANK(key), STR_OR_BLANK(value)); err = ESP_FAIL; continue; @@ -1271,7 +1240,7 @@ static esp_err_t save_known_config(cJSON* known_item, const char* name, FILE* f) fprintf(f, "Storing %s=%s\n", key, value); // err = config_set_value(NVS_TYPE_STR,key,value); // TODO: Add support for the commented code - if (err) { + if(err) { fprintf(f, "Failed to store config value: %s\n", esp_err_to_name(err)); break; } @@ -1287,12 +1256,10 @@ static esp_err_t save_known_config(cJSON* known_item, const char* name, FILE* f) err = ESP_FAIL; } - if (err == ESP_OK) { + if(err == ESP_OK) { // err = config_set_value(NVS_TYPE_STR,"board_model",name); // TODO: Add support for the commented code - if (err != ESP_OK) { - fprintf(f, "Failed to save board model %s\n", name); - } + if(err != ESP_OK) { fprintf(f, "Failed to save board model %s\n", name); } } return err; @@ -1564,76 +1531,53 @@ static void register_squeezelite_config(void) { } void dummy_register_cmd() {} - void register_wifi_commands() { // WiFi Join Command wifi_join_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to connect to"); wifi_join_args.password = arg_str0(NULL, NULL, "[password]", "Password for the access point"); wifi_join_args.end = arg_end(2); const esp_console_cmd_t join_cmd = { - .command = "wifi_join", - .help = "Join a WiFi network", - .hint = NULL, - .func = &do_wifi_join, - .argtable = &wifi_join_args - }; + .command = "wifi_join", .help = "Join a WiFi network", .hint = NULL, .func = &do_wifi_join, .argtable = &wifi_join_args}; ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&join_cmd)); - wifi_add_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to connect to"); + wifi_add_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to connect to"); wifi_add_args.password = arg_str0(NULL, NULL, "[password]", "Password for the access point"); wifi_add_args.end = arg_end(2); - const esp_console_cmd_t add_cmd = { - .command = "wifi_add", + const esp_console_cmd_t add_cmd = {.command = "wifi_add", .help = "Adds a WiFi network to known list without connecting to it", .hint = NULL, .func = &do_wifi_add, - .argtable = &wifi_add_args - }; + .argtable = &wifi_add_args}; ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&add_cmd)); // WiFi Delete Command wifi_delete_args.ap_name = arg_str1(NULL, NULL, "", "Access Point to forget"); wifi_delete_args.end = arg_end(1); const esp_console_cmd_t delete_cmd = { - .command = "wifi_delete", - .help = "Delete a WiFi network", - .hint = NULL, - .func = &do_wifi_delete, - .argtable = &wifi_delete_args - }; + .command = "wifi_delete", .help = "Delete a WiFi network", .hint = NULL, .func = &do_wifi_delete, .argtable = &wifi_delete_args}; ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&delete_cmd)); - // WiFi Scan Command + // WiFi Scan Command wifi_scan_args.end = arg_end(1); const esp_console_cmd_t scan_cmd = { - .command = "wifi_scan", - .help = "Scan for available WiFi networks", - .hint = NULL, - .func = &do_wifi_scan, - .argtable = &wifi_scan_args - }; + .command = "wifi_scan", .help = "Scan for available WiFi networks", .hint = NULL, .func = &do_wifi_scan, .argtable = &wifi_scan_args}; ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&scan_cmd)); // WiFi Status Command wifi_status_args.end = arg_end(1); - const esp_console_cmd_t status_cmd = { - .command = "wifi_status", + const esp_console_cmd_t status_cmd = {.command = "wifi_status", .help = "Show current WiFi connection status", .hint = NULL, .func = &do_wifi_status, - .argtable = &wifi_status_args - }; + .argtable = &wifi_status_args}; ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&status_cmd)); - // WiFi Reset Command wifi_reset_args.end = arg_end(1); - const esp_console_cmd_t reset_cmd = { - .command = "wifi_reset", + const esp_console_cmd_t reset_cmd = {.command = "wifi_reset", .help = "Reset WiFi configuration to default settings", .hint = NULL, .func = &do_wifi_reset, - .argtable = &wifi_reset_args - }; + .argtable = &wifi_reset_args}; ESP_ERROR_CHECK_WITHOUT_ABORT(esp_console_cmd_register(&reset_cmd)); } void register_config_cmd(void) { @@ -1646,7 +1590,7 @@ void register_config_cmd(void) { // #endif // register_bt_source_config(); #if CONFIG_WITH_CONFIG_UI - if (!is_dac_config_locked()) { + if(!is_dac_config_locked()) { register_i2s_config(); } else { #if defined(CONFIG_WITH_METRICS) diff --git a/components/platform_console/cmd_i2ctools.c b/components/platform_console/cmd_i2ctools.c index 0ee66c72..49330c54 100644 --- a/components/platform_console/cmd_i2ctools.c +++ b/components/platform_console/cmd_i2ctools.c @@ -41,7 +41,6 @@ const char* desc_spiconfig = "SPI Bus Parameters"; const char* desc_i2c = "I2C Bus Parameters"; const char* desc_display = "Display"; - static struct { struct arg_int* port; struct arg_int* chip_address; @@ -67,7 +66,7 @@ static struct { struct arg_int* size; struct arg_end* end; } i2cdump_args; -#endif +#endif static struct { struct arg_int* port; @@ -113,18 +112,11 @@ bool is_i2c_started(i2c_port_t port) { ESP_LOGD(TAG, "Determining if i2c is started on port %u", port); i2c_cmd_handle_t cmd = i2c_cmd_link_create(); ret = i2c_master_start(cmd); - if (ret == ESP_OK) { - ret = i2c_master_write_byte(cmd, WRITE_BIT, ACK_CHECK_EN); - } - if (ret == ESP_OK) { - ret = i2c_master_stop(cmd); - } - if (ret == ESP_OK) { - ret = i2c_master_cmd_begin(port, cmd, 50 / portTICK_PERIOD_MS); - } + if(ret == ESP_OK) { ret = i2c_master_write_byte(cmd, WRITE_BIT, ACK_CHECK_EN); } + if(ret == ESP_OK) { ret = i2c_master_stop(cmd); } + if(ret == ESP_OK) { ret = i2c_master_cmd_begin(port, cmd, 50 / portTICK_PERIOD_MS); } i2c_cmd_link_delete(cmd); - ESP_LOGD(TAG, "i2c is %s. %s", ret != ESP_ERR_INVALID_STATE ? "started" : "not started", - esp_err_to_name(ret)); + ESP_LOGD(TAG, "i2c is %s. %s", ret != ESP_ERR_INVALID_STATE ? "started" : "not started", esp_err_to_name(ret)); return (ret != ESP_ERR_INVALID_STATE); } @@ -137,144 +129,101 @@ typedef struct { // the list was taken from https://i2cdevices.org/addresses // on 2020-01-16 -static const i2c_db_t i2c_db[] = {{.address = 0x00, .description = "Unknown"}, - {.address = 0x01, .description = "Unknown"}, {.address = 0x02, .description = "Unknown"}, - {.address = 0x03, .description = "Unknown"}, {.address = 0x04, .description = "Unknown"}, - {.address = 0x05, .description = "Unknown"}, {.address = 0x06, .description = "Unknown"}, - {.address = 0x07, .description = "Unknown"}, {.address = 0x08, .description = "Unknown"}, - {.address = 0x0c, .description = "AK8975"}, {.address = 0x0d, .description = "AK8975"}, - {.address = 0x0e, .description = "MAG3110 AK8975 IST-8310"}, - {.address = 0x0f, .description = "AK8975"}, +static const i2c_db_t i2c_db[] = {{.address = 0x00, .description = "Unknown"}, {.address = 0x01, .description = "Unknown"}, + {.address = 0x02, .description = "Unknown"}, {.address = 0x03, .description = "Unknown"}, {.address = 0x04, .description = "Unknown"}, + {.address = 0x05, .description = "Unknown"}, {.address = 0x06, .description = "Unknown"}, {.address = 0x07, .description = "Unknown"}, + {.address = 0x08, .description = "Unknown"}, {.address = 0x0c, .description = "AK8975"}, {.address = 0x0d, .description = "AK8975"}, + {.address = 0x0e, .description = "MAG3110 AK8975 IST-8310"}, {.address = 0x0f, .description = "AK8975"}, {.address = 0x10, .description = "VEML7700 VML6075 VEML6075 ES8388"}, - {.address = 0x11, - .description = "Si4713 SAA5246 SAA5243P/K SAA5243P/L SAA5243P/E SAA5243P/H ES8388"}, - {.address = 0x12, .description = "SEN-17374"}, - {.address = 0x13, .description = "VCNL40x0 SEN-17374"}, - {.address = 0x18, .description = "MCP9808 LIS3DH LSM303 COM-15093"}, - {.address = 0x19, .description = "MCP9808 LIS3DH LSM303 COM-15093"}, + {.address = 0x11, .description = "Si4713 SAA5246 SAA5243P/K SAA5243P/L SAA5243P/E SAA5243P/H ES8388"}, + {.address = 0x12, .description = "SEN-17374"}, {.address = 0x13, .description = "VCNL40x0 SEN-17374"}, + {.address = 0x18, .description = "MCP9808 LIS3DH LSM303 COM-15093"}, {.address = 0x19, .description = "MCP9808 LIS3DH LSM303 COM-15093"}, {.address = 0x1a, .description = "AC101 MCP9808"}, {.address = 0x1b, .description = "MCP9808"}, - {.address = 0x1c, .description = "MCP9808 MMA845x FXOS8700"}, - {.address = 0x1d, .description = "MCP9808 MMA845x ADXL345 FXOS8700"}, - {.address = 0x1e, .description = "HMC5883 LSM303 MCP9808 LSM303 FXOS8700"}, - {.address = 0x1f, .description = "MCP9808 FXOS8700"}, + {.address = 0x1c, .description = "MCP9808 MMA845x FXOS8700"}, {.address = 0x1d, .description = "MCP9808 MMA845x ADXL345 FXOS8700"}, + {.address = 0x1e, .description = "HMC5883 LSM303 MCP9808 LSM303 FXOS8700"}, {.address = 0x1f, .description = "MCP9808 FXOS8700"}, {.address = 0x20, .description = "TCA9554 MCP23008 MA12070P MCP23017 Chirp! FXAS21002"}, {.address = 0x21, .description = "FXAS21002 MCP23008 MCP23017 SAA4700 MA12070P TCA9554"}, {.address = 0x22, .description = "ES8388 MCP23008 MCP23017 PCA1070 MA12070P TCA9554"}, {.address = 0x23, .description = "MCP23008 MCP23017 SAA4700 MA12070P TCA9554"}, {.address = 0x24, .description = "TCA9554 MCP23008 PCD3312C MCP23017 PCD3311C"}, - {.address = 0x25, .description = "TCA9554 MCP23008 PCD3312C MCP23017 PCD3311C"}, - {.address = 0x26, .description = "MCP23008 MCP23017 TCA9554"}, - {.address = 0x27, .description = "MCP23008 MCP23017 HIH6130 TCA9554"}, - {.address = 0x28, .description = "BNO055 CAP1188"}, - {.address = 0x29, .description = "BNO055 VL53L0x VL6180X CAP1188 TCS34725 TSL2591"}, - {.address = 0x2a, .description = "CAP1188"}, {.address = 0x2b, .description = "CAP1188"}, - {.address = 0x2c, .description = "CAP1188 AD5248 AD5251 AD5252 CAT5171"}, - {.address = 0x2d, .description = "CAP1188 AD5248 AD5251 AD5252 CAT5171"}, - {.address = 0x2e, .description = "AD5248 AD5251 AD5252 LPS22HB"}, - {.address = 0x2f, .description = "AD5248 AD5243 AD5251 AD5252"}, - {.address = 0x30, .description = "SAA2502"}, {.address = 0x31, .description = "SAA2502"}, - {.address = 0x33, .description = "MLX90640"}, + {.address = 0x25, .description = "TCA9554 MCP23008 PCD3312C MCP23017 PCD3311C"}, {.address = 0x26, .description = "MCP23008 MCP23017 TCA9554"}, + {.address = 0x27, .description = "MCP23008 MCP23017 HIH6130 TCA9554"}, {.address = 0x28, .description = "BNO055 CAP1188"}, + {.address = 0x29, .description = "BNO055 VL53L0x VL6180X CAP1188 TCS34725 TSL2591"}, {.address = 0x2a, .description = "CAP1188"}, + {.address = 0x2b, .description = "CAP1188"}, {.address = 0x2c, .description = "CAP1188 AD5248 AD5251 AD5252 CAT5171"}, + {.address = 0x2d, .description = "CAP1188 AD5248 AD5251 AD5252 CAT5171"}, {.address = 0x2e, .description = "AD5248 AD5251 AD5252 LPS22HB"}, + {.address = 0x2f, .description = "AD5248 AD5243 AD5251 AD5252"}, {.address = 0x30, .description = "SAA2502"}, + {.address = 0x31, .description = "SAA2502"}, {.address = 0x33, .description = "MLX90640"}, {.address = 0x38, .description = "FT6x06 VEML6070 BMA150 SAA1064 SEN-15892 PCF8574AP"}, - {.address = 0x39, .description = "TSL2561 APDS-9960 VEML6070 SAA1064 PCF8574AP"}, - {.address = 0x3a, .description = "PCF8577C SAA1064 PCF8574AP"}, + {.address = 0x39, .description = "TSL2561 APDS-9960 VEML6070 SAA1064 PCF8574AP"}, {.address = 0x3a, .description = "PCF8577C SAA1064 PCF8574AP"}, {.address = 0x3b, .description = "SAA1064 PCF8569 PCF8574AP"}, {.address = 0x3c, .description = "SSD1305 SSD1306 PCF8578 PCF8569 SH1106 PCF8574AP"}, - {.address = 0x3d, .description = "SSD1305 SSD1306 PCF8578 SH1106 PCF8574AP"}, - {.address = 0x3e, .description = "PCF8574AP"}, {.address = 0x3f, .description = "PCF8574AP"}, + {.address = 0x3d, .description = "SSD1305 SSD1306 PCF8578 SH1106 PCF8574AP"}, {.address = 0x3e, .description = "PCF8574AP"}, + {.address = 0x3f, .description = "PCF8574AP"}, {.address = 0x40, .description = "Si7021 HTU21D-F TMP007 TMP006 PCA9685 INA219 TEA6330 TEA6300 TDA9860 " "TEA6320 TDA8421 NE5751 INA260 PCF8574"}, {.address = 0x41, .description = "TMP007 TDA8421 TDA8424 STMPE610 PCF8574 STMPE811 NE5751 INA260 TDA8425 " "TMP006 TDA9860 PCA9685 INA219 TDA8426"}, - {.address = 0x42, - .description = "TMP007 TDA8417 HDC1008 PCF8574 INA260 TDA8415 TMP006 PCA9685 INA219"}, + {.address = 0x42, .description = "TMP007 TDA8417 HDC1008 PCF8574 INA260 TDA8415 TMP006 PCA9685 INA219"}, {.address = 0x43, .description = "TMP007 HDC1008 PCF8574 INA260 TMP006 PCA9685 INA219"}, {.address = 0x44, .description = "TMP007 TMP006 PCA9685 INA219 STMPE610 SHT31 ISL29125 STMPE811 TDA4688 " "TDA4672 TDA4780 TDA4670 TDA8442 TDA4687 TDA4671 TDA4680 INA260 PCF8574"}, - {.address = 0x45, - .description = "TMP007 TDA7433 PCF8574 TDA8376 INA260 TMP006 PCA9685 INA219 SHT31"}, + {.address = 0x45, .description = "TMP007 TDA7433 PCF8574 TDA8376 INA260 TMP006 PCA9685 INA219 SHT31"}, {.address = 0x46, .description = "TMP007 PCF8574 TDA8370 INA260 TMP006 PCA9685 INA219 TDA9150"}, {.address = 0x47, .description = "TMP007 PCF8574 INA260 TMP006 PCA9685 INA219"}, {.address = 0x48, .description = "PCA9685 INA219 PN532 TMP102 INA260 ADS1115 PCF8574 ADS7828"}, - {.address = 0x49, - .description = "TSL2561 PCA9685 INA219 TMP102 INA260 ADS1115 AS7262 PCF8574 ADS7828"}, - {.address = 0x4a, - .description = "ADS7828 PCF8574 ADS1115 INA260 PCA9685 MAX44009 INA219 TMP102"}, - {.address = 0x4b, - .description = "ADS7828 PCF8574 ADS1115 INA260 PCA9685 MAX44009 INA219 TMP102"}, - {.address = 0x4c, .description = "PCA9685 INA219 INA260 PCF8574"}, - {.address = 0x4d, .description = "PCA9685 INA219 INA260 PCF8574"}, - {.address = 0x4e, .description = "PCA9685 INA219 INA260 PCF8574"}, - {.address = 0x4f, .description = "PCA9685 INA219 INA260 PCF8574"}, - {.address = 0x50, .description = "PCA9685 MB85RC"}, - {.address = 0x51, .description = "PCA9685 MB85RC VCNL4200"}, + {.address = 0x49, .description = "TSL2561 PCA9685 INA219 TMP102 INA260 ADS1115 AS7262 PCF8574 ADS7828"}, + {.address = 0x4a, .description = "ADS7828 PCF8574 ADS1115 INA260 PCA9685 MAX44009 INA219 TMP102"}, + {.address = 0x4b, .description = "ADS7828 PCF8574 ADS1115 INA260 PCA9685 MAX44009 INA219 TMP102"}, + {.address = 0x4c, .description = "PCA9685 INA219 INA260 PCF8574"}, {.address = 0x4d, .description = "PCA9685 INA219 INA260 PCF8574"}, + {.address = 0x4e, .description = "PCA9685 INA219 INA260 PCF8574"}, {.address = 0x4f, .description = "PCA9685 INA219 INA260 PCF8574"}, + {.address = 0x50, .description = "PCA9685 MB85RC"}, {.address = 0x51, .description = "PCA9685 MB85RC VCNL4200"}, {.address = 0x52, .description = "PCA9685 MB85RC Nunchuck controller APDS-9250 SI1133"}, - {.address = 0x53, .description = "ADXL345 PCA9685 MB85RC"}, - {.address = 0x54, .description = "PCA9685 MB85RC"}, - {.address = 0x55, .description = "PCA9685 MB85RC MAX30101 SI1133"}, - {.address = 0x56, .description = "PCA9685 MB85RC"}, - {.address = 0x57, .description = "PCA9685 MB85RC MAX3010x"}, - {.address = 0x58, .description = "PCA9685 TPA2016 SGP30"}, - {.address = 0x59, .description = "PCA9685"}, - {.address = 0x5a, .description = "MPR121 MLX90614 CCS811 PCA9685 DRV2605"}, - {.address = 0x5b, .description = "PCA9685 CCS811 MPR121"}, - {.address = 0x5c, .description = "PCA9685 AM2315 MPR121"}, + {.address = 0x53, .description = "ADXL345 PCA9685 MB85RC"}, {.address = 0x54, .description = "PCA9685 MB85RC"}, + {.address = 0x55, .description = "PCA9685 MB85RC MAX30101 SI1133"}, {.address = 0x56, .description = "PCA9685 MB85RC"}, + {.address = 0x57, .description = "PCA9685 MB85RC MAX3010x"}, {.address = 0x58, .description = "PCA9685 TPA2016 SGP30"}, + {.address = 0x59, .description = "PCA9685"}, {.address = 0x5a, .description = "MPR121 MLX90614 CCS811 PCA9685 DRV2605"}, + {.address = 0x5b, .description = "PCA9685 CCS811 MPR121"}, {.address = 0x5c, .description = "PCA9685 AM2315 MPR121"}, {.address = 0x5d, .description = "PCA9685 MPR121"}, {.address = 0x5e, .description = "PCA9685"}, {.address = 0x5f, .description = "PCA9685 HTS221"}, {.address = 0x60, .description = "SI1132 Si5351A ATECC608A TSA5511 ATECC508A SAB3035 MCP4725A0 SAB3037 " "PCA9685 MCP4725A1 TEA5767 MPL3115A2 MPL115A2 Si1145"}, - {.address = 0x61, - .description = "Si5351A TSA5511 SAB3035 MCP4725A0 SAB3037 TEA6100 PCA9685 MCP4725A1"}, - {.address = 0x62, - .description = "SCD40-D-R2 TSA5511 SAB3035 UMA1014T SAB3037 PCA9685 MCP4725A1"}, + {.address = 0x61, .description = "Si5351A TSA5511 SAB3035 MCP4725A0 SAB3037 TEA6100 PCA9685 MCP4725A1"}, + {.address = 0x62, .description = "SCD40-D-R2 TSA5511 SAB3035 UMA1014T SAB3037 PCA9685 MCP4725A1"}, {.address = 0x63, .description = "Si4713 TSA5511 SAB3035 UMA1014T SAB3037 PCA9685 MCP4725A1"}, - {.address = 0x64, .description = "PCA9685 MCP4725A2 MCP4725A1"}, - {.address = 0x65, .description = "PCA9685 MCP4725A2 MCP4725A1"}, - {.address = 0x66, .description = "PCA9685 MCP4725A3 IS31FL3731 MCP4725A1"}, - {.address = 0x67, .description = "PCA9685 MCP4725A3 MCP4725A1"}, - {.address = 0x68, - .description = - "MPU-9250 ICM-20948 MPU6050 AMG8833 DS3231 PCA9685 PCF8573 PCF8523 DS1307 ITG3200"}, - {.address = 0x69, - .description = "MPU-9250 ICM-20948 MPU6050 AMG8833 PCA9685 PCF8573 ITG3200 SPS30"}, - {.address = 0x6a, .description = "PCA9685 L3GD20H PCF8573"}, - {.address = 0x6b, .description = "PCA9685 L3GD20H PCF8573"}, - {.address = 0x6c, .description = "PCA9685"}, {.address = 0x6d, .description = "PCA9685"}, - {.address = 0x6e, .description = "PCA9685"}, - {.address = 0x6f, .description = "PCA9685 MCP7940N"}, - {.address = 0x70, .description = "PCA9685 TCA9548 HT16K33 SHTC3"}, - {.address = 0x71, .description = "PCA9685 TCA9548 HT16K33"}, - {.address = 0x72, .description = "PCA9685 TCA9548 HT16K33"}, - {.address = 0x73, .description = "PCA9685 TCA9548 HT16K33"}, - {.address = 0x74, .description = "PCA9685 TCA9548 HT16K33"}, + {.address = 0x64, .description = "PCA9685 MCP4725A2 MCP4725A1"}, {.address = 0x65, .description = "PCA9685 MCP4725A2 MCP4725A1"}, + {.address = 0x66, .description = "PCA9685 MCP4725A3 IS31FL3731 MCP4725A1"}, {.address = 0x67, .description = "PCA9685 MCP4725A3 MCP4725A1"}, + {.address = 0x68, .description = "MPU-9250 ICM-20948 MPU6050 AMG8833 DS3231 PCA9685 PCF8573 PCF8523 DS1307 ITG3200"}, + {.address = 0x69, .description = "MPU-9250 ICM-20948 MPU6050 AMG8833 PCA9685 PCF8573 ITG3200 SPS30"}, + {.address = 0x6a, .description = "PCA9685 L3GD20H PCF8573"}, {.address = 0x6b, .description = "PCA9685 L3GD20H PCF8573"}, + {.address = 0x6c, .description = "PCA9685"}, {.address = 0x6d, .description = "PCA9685"}, {.address = 0x6e, .description = "PCA9685"}, + {.address = 0x6f, .description = "PCA9685 MCP7940N"}, {.address = 0x70, .description = "PCA9685 TCA9548 HT16K33 SHTC3"}, + {.address = 0x71, .description = "PCA9685 TCA9548 HT16K33"}, {.address = 0x72, .description = "PCA9685 TCA9548 HT16K33"}, + {.address = 0x73, .description = "PCA9685 TCA9548 HT16K33"}, {.address = 0x74, .description = "PCA9685 TCA9548 HT16K33"}, {.address = 0x75, .description = "PCA9685 TCA9548 HT16K33"}, - {.address = 0x76, - .description = "BME688 BME680 MS5611 MS5607 HT16K33 PCA9685 BME280 BMP280 TCA9548"}, + {.address = 0x76, .description = "BME688 BME680 MS5611 MS5607 HT16K33 PCA9685 BME280 BMP280 TCA9548"}, {.address = 0x77, .description = "PCA9685 TCA9548 HT16K33 IS31FL3731 BME280 BMP280 MS5607 BMP180 BMP085 " "BMA180 MS5611 BME680 BME688"}, - {.address = 0x78, .description = "PCA9685"}, {.address = 0x79, .description = "PCA9685"}, - {.address = 0x7a, .description = "PCA9685"}, {.address = 0x7b, .description = "PCA9685"}, - {.address = 0x7c, .description = "PCA9685"}, {.address = 0x7d, .description = "PCA9685"}, - {.address = 0x7e, .description = "PCA9685"}, {.address = 0x7f, .description = "PCA9685"}, - {.address = 0, .description = NULL}}; + {.address = 0x78, .description = "PCA9685"}, {.address = 0x79, .description = "PCA9685"}, {.address = 0x7a, .description = "PCA9685"}, + {.address = 0x7b, .description = "PCA9685"}, {.address = 0x7c, .description = "PCA9685"}, {.address = 0x7d, .description = "PCA9685"}, + {.address = 0x7e, .description = "PCA9685"}, {.address = 0x7f, .description = "PCA9685"}, {.address = 0, .description = NULL}}; const char* i2c_get_description(uint8_t address) { uint8_t i = 0; - while (i2c_db[i].description && i2c_db[i].address != address) - i++; + while(i2c_db[i].description && i2c_db[i].address != address) i++; return i2c_db[i].description ? i2c_db[i].description : "Unlisted"; } #endif static esp_err_t i2c_get_port(int port, i2c_port_t* i2c_port) { - if (port >= I2C_NUM_MAX) { + if(port >= I2C_NUM_MAX) { log_send_messaging(MESSAGING_ERROR, "Wrong port number: %d", port); return ESP_FAIL; } - switch (port) { + switch(port) { case 0: *i2c_port = I2C_NUM_0; break; @@ -319,19 +268,15 @@ static int do_i2c_set_display(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cdisp_args); display_config_t config = {.back = -1, .CS_pin = -1, .RST_pin = -1, .depth = 0}; char* nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config"); - if (nvs_item && strlen(nvs_item) > 0) { - bHasi2cConfig = true; - } + if(nvs_item && strlen(nvs_item) > 0) { bHasi2cConfig = true; } FREE_AND_NULL(nvs_item); nvs_item = config_alloc_get(NVS_TYPE_STR, "spi_config"); - if (nvs_item && strlen(nvs_item) > 0) { - bHasSpiConfig = true; - } + if(nvs_item && strlen(nvs_item) > 0) { bHasSpiConfig = true; } FREE_AND_NULL(nvs_item); /* Check "--clear" option */ - if (i2cdisp_args.clear->count) { + if(i2cdisp_args.clear->count) { cmd_send_messaging(argv[0], MESSAGING_WARNING, "Display config cleared"); config_set_value(NVS_TYPE_STR, "display_config", ""); return 0; @@ -339,18 +284,18 @@ static int do_i2c_set_display(int argc, char** argv) { char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f == NULL) { + if(f == NULL) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream."); return 1; } - if (nerrors > 0) { + if(nerrors > 0) { arg_print_errors(f, i2cdisp_args.end, desc_display); fclose(f); return 1; } /* Check "--type" option */ - if (i2cdisp_args.type->count) { - if (strcasecmp(i2c_name_type, i2cdisp_args.type->sval[0]) == 0) { + if(i2cdisp_args.type->count) { + if(strcasecmp(i2c_name_type, i2cdisp_args.type->sval[0]) == 0) { config.type = i2c_name_type; } else { config.type = spi_name_type; @@ -359,24 +304,24 @@ static int do_i2c_set_display(int argc, char** argv) { config.type = i2c_name_type; } /* Check "--address" option */ - if (strcasecmp(config.type, "I2C") == 0) { - if (i2cdisp_args.address->count > 0) { + if(strcasecmp(config.type, "I2C") == 0) { + if(i2cdisp_args.address->count > 0) { config.address = i2cdisp_args.address->ival[0]; } else { config.address = 60; } - if (!bHasi2cConfig) { + if(!bHasi2cConfig) { fprintf(f, "I2C bus has to be configured first. \n"); nerrors++; } } else { // SPI Bus connection - if (!bHasSpiConfig) { + if(!bHasSpiConfig) { fprintf(f, "SPI bus has to be configured first. \n"); nerrors++; } /* Check "--speed" option */ - if (i2cdisp_args.speed->count) { + if(i2cdisp_args.speed->count) { config.speed = i2cdisp_args.speed->ival[0]; } else { config.speed = 8000000; @@ -384,7 +329,7 @@ static int do_i2c_set_display(int argc, char** argv) { /* Check "--cs" option */ nerrors += is_output_gpio(i2cdisp_args.cs, f, &config.CS_pin, false); /* Check "--mode" option */ - if (i2cdisp_args.mode->count) { + if(i2cdisp_args.mode->count) { config.mode = i2cdisp_args.mode->ival[0]; } else { config.mode = 0; @@ -393,28 +338,20 @@ static int do_i2c_set_display(int argc, char** argv) { nerrors += is_output_gpio(i2cdisp_args.reset, f, &config.RST_pin, false); /* Check "--width" option */ - if (i2cdisp_args.width->count) { - config.width = i2cdisp_args.width->ival[0]; - } + if(i2cdisp_args.width->count) { config.width = i2cdisp_args.width->ival[0]; } /* Check "--height" option */ - if (i2cdisp_args.height->count) { - config.height = i2cdisp_args.height->ival[0]; - } + if(i2cdisp_args.height->count) { config.height = i2cdisp_args.height->ival[0]; } /* Check "--driver" option */ - if (i2cdisp_args.driver->count) { - config.drivername = display_conf_get_driver_name(i2cdisp_args.driver->sval[0]); - } - if (i2cdisp_args.depth->count > 0 && strcasecmp(config.drivername, "SSD1326") == 0) { - config.depth = i2cdisp_args.depth->ival[0]; - } + if(i2cdisp_args.driver->count) { config.drivername = display_conf_get_driver_name(i2cdisp_args.driver->sval[0]); } + if(i2cdisp_args.depth->count > 0 && strcasecmp(config.drivername, "SSD1326") == 0) { config.depth = i2cdisp_args.depth->ival[0]; } /* Check "--back" option */ nerrors += is_output_gpio(i2cdisp_args.back, f, &config.back, false); - if (!config.drivername || !display_is_valid_driver(config.drivername)) { + if(!config.drivername || !display_is_valid_driver(config.drivername)) { fprintf(f, "Unsupported display driver %s\n", config.drivername); nerrors++; } - if (!strcasestr(config.type, "I2C") && !strcasestr(config.type, "SPI")) { + if(!strcasestr(config.type, "I2C") && !strcasestr(config.type, "SPI")) { fprintf(f, "Invalid display type %s\n", config.type); nerrors++; } @@ -423,17 +360,15 @@ static int do_i2c_set_display(int argc, char** argv) { config.vflip = i2cdisp_args.vflip->count > 0; config.invert = i2cdisp_args.invert->count > 0; - if (nerrors == 0) { + if(nerrors == 0) { fprintf(f, "Saving display configuration\n"); esp_err_t err = config_display_set(&config); - if (err != ESP_OK) { + if(err != ESP_OK) { fprintf(f, "Error: %s\n", esp_err_to_name(err)); nerrors++; } } - if (!nerrors) { - fprintf(f, "Done.\n"); - } + if(!nerrors) { fprintf(f, "Done.\n"); } fflush(f); cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); fclose(f); @@ -442,17 +377,13 @@ static int do_i2c_set_display(int argc, char** argv) { } static int do_spiconfig_cmd(int argc, char** argv) { - static spi_bus_config_t spi_config = {.mosi_io_num = -1, - .sclk_io_num = -1, - .miso_io_num = -1, - .quadwp_io_num = -1, - .quadhd_io_num = -1}; + static spi_bus_config_t spi_config = {.mosi_io_num = -1, .sclk_io_num = -1, .miso_io_num = -1, .quadwp_io_num = -1, .quadhd_io_num = -1}; int dc = -1, host = 0; esp_err_t err = ESP_OK; int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&spiconfig_args); /* Check "--clear" option */ - if (spiconfig_args.clear->count) { + if(spiconfig_args.clear->count) { cmd_send_messaging(argv[0], MESSAGING_WARNING, "SPI config cleared.\n"); config_set_value(NVS_TYPE_STR, "spi_config", ""); return 0; @@ -461,11 +392,11 @@ static int do_spiconfig_cmd(int argc, char** argv) { char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f == NULL) { + if(f == NULL) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream.\n"); return 1; } - if (nerrors > 0) { + if(nerrors > 0) { arg_print_errors(f, spiconfig_args.end, desc_spiconfig); fclose(f); return 1; @@ -477,22 +408,19 @@ static int do_spiconfig_cmd(int argc, char** argv) { nerrors += is_output_gpio(spiconfig_args.dc, f, &dc, true); nerrors += is_output_gpio(spiconfig_args.host, f, &host, true); - if (!nerrors) { - fprintf(f, "Configuring SPI data=%d clock=%d host=%u dc: %d\n", spi_config.mosi_io_num, - spi_config.sclk_io_num, host, dc); + if(!nerrors) { + fprintf(f, "Configuring SPI data=%d clock=%d host=%u dc: %d\n", spi_config.mosi_io_num, spi_config.sclk_io_num, host, dc); err = spi_bus_initialize(host, &spi_config, SPI_DMA_CH_AUTO); - if (err != ESP_OK) { - if (err == ESP_ERR_INVALID_STATE) { + if(err != ESP_OK) { + if(err == ESP_ERR_INVALID_STATE) { // if user is changing the host number, we need to try freeing both hosts - if ((err = spi_bus_free(host)) != ESP_OK && - (err = spi_bus_free(host == 1 ? 2 : 1)) != ESP_OK) { + if((err = spi_bus_free(host)) != ESP_OK && (err = spi_bus_free(host == 1 ? 2 : 1)) != ESP_OK) { fprintf(f, "SPI bus init failed. Please clear SPI configuration, restart the device " "and try again. %s\n", esp_err_to_name(err)); nerrors++; - } else if ((err = spi_bus_initialize(host, &spi_config, SPI_DMA_CH_AUTO)) != - ESP_OK) { + } else if((err = spi_bus_initialize(host, &spi_config, SPI_DMA_CH_AUTO)) != ESP_OK) { fprintf(f, "Failed to initialize SPI Bus. %s\n", esp_err_to_name(err)); nerrors++; } @@ -503,13 +431,11 @@ static int do_spiconfig_cmd(int argc, char** argv) { } } - if (!nerrors) { + if(!nerrors) { fprintf(f, "Storing SPI parameters.\n"); nerrors += (config_spi_set(&spi_config, host, dc) != ESP_OK); } - if (!nerrors) { - fprintf(f, "Done.\n"); - } + if(!nerrors) { fprintf(f, "Done.\n"); } fflush(f); cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); fclose(f); @@ -521,11 +447,11 @@ static int do_spiconfig_cmd(int argc, char** argv) { static int do_i2cconfig_cmd(int argc, char** argv) { esp_err_t err = ESP_OK; // i2c_config_t conf = {.mode = I2C_MODE_MASTER, - // .sda_io_num = 19, - // .sda_pullup_en = GPIO_PULLUP_ENABLE, - // .scl_io_num = 18, - // .scl_pullup_en = GPIO_PULLUP_ENABLE, - // .master.clk_speed = 100000}; + // .sda_io_num = 19, + // .sda_pullup_en = GPIO_PULLUP_ENABLE, + // .scl_io_num = 18, + // .scl_pullup_en = GPIO_PULLUP_ENABLE, + // .master.clk_speed = 100000}; int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cconfig_args); /* Check "--clear" option */ @@ -536,71 +462,71 @@ static int do_i2cconfig_cmd(int argc, char** argv) { // } // TODO: Add support for the commented code -// char* buf = NULL; -// size_t buf_size = 0; -// FILE* f = open_memstream(&buf, &buf_size); -// if (f == NULL) { -// cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream.\n"); -// return 1; -// } -// if (nerrors > 0) { -// arg_print_errors(f, i2cconfig_args.end, desc_i2c); -// fclose(f); -// return 1; -// } -// /* Check "--port" option */ -// if (i2cconfig_args.port->count) { -// if (i2c_get_port(i2cconfig_args.port->ival[0], &i2c_port) != ESP_OK) { -// fprintf(f, "Invalid port %u \n", i2cconfig_args.port->ival[0]); -// nerrors++; -// } -// } -// /* Check "--freq" option */ -// if (i2cconfig_args.freq->count) { -// conf.master.clk_speed = i2cconfig_args.freq->ival[0]; -// } + // char* buf = NULL; + // size_t buf_size = 0; + // FILE* f = open_memstream(&buf, &buf_size); + // if (f == NULL) { + // cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream.\n"); + // return 1; + // } + // if (nerrors > 0) { + // arg_print_errors(f, i2cconfig_args.end, desc_i2c); + // fclose(f); + // return 1; + // } + // /* Check "--port" option */ + // if (i2cconfig_args.port->count) { + // if (i2c_get_port(i2cconfig_args.port->ival[0], &i2c_port) != ESP_OK) { + // fprintf(f, "Invalid port %u \n", i2cconfig_args.port->ival[0]); + // nerrors++; + // } + // } + // /* Check "--freq" option */ + // if (i2cconfig_args.freq->count) { + // conf.master.clk_speed = i2cconfig_args.freq->ival[0]; + // } -// nerrors += is_output_gpio(i2cconfig_args.sda, f, &conf.sda_io_num, true); -// nerrors += is_output_gpio(i2cconfig_args.scl, f, &conf.scl_io_num, true); - -// #ifdef CONFIG_I2C_LOCKED -// if (i2c_port == I2C_NUM_0) { -// i2c_port = I2C_NUM_1; -// fprintf(f, "can't use i2c port 0 when locked by config. Changing to port 1.\n"); -// } -// #endif + // nerrors += is_output_gpio(i2cconfig_args.sda, f, &conf.sda_io_num, true); + // nerrors += is_output_gpio(i2cconfig_args.scl, f, &conf.scl_io_num, true); -// if (!nerrors) { -// fprintf(f, "Uninstalling i2c driver from port %u if needed\n", i2c_port); -// if (is_i2c_started(i2c_port)) { -// if ((err = i2c_driver_delete(i2c_port)) != ESP_OK) { -// fprintf(f, "i2c driver delete failed. %s\n", esp_err_to_name(err)); -// nerrors++; -// } -// } -// } -// if (!nerrors) { -// if ((err = i2c_master_driver_initialize(argv[0], &conf)) == ESP_OK) { -// if ((err = i2c_master_driver_install(argv[0])) != ESP_OK) { -// nerrors++; -// } else { -// fprintf(f, "i2c driver successfully started.\n"); -// } -// } else { -// nerrors++; -// } -// } -// if (!nerrors) { -// fprintf(f, "Storing i2c parameters.\n"); -// config_i2c_set(&conf, i2c_port); -// } -// if (!nerrors) { -// fprintf(f, "Done.\n"); -// } -// fflush(f); -// cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); -// fclose(f); -// FREE_AND_NULL(buf); + // #ifdef CONFIG_I2C_LOCKED + // if (i2c_port == I2C_NUM_0) { + // i2c_port = I2C_NUM_1; + // fprintf(f, "can't use i2c port 0 when locked by config. Changing to port 1.\n"); + // } + // #endif + + // if (!nerrors) { + // fprintf(f, "Uninstalling i2c driver from port %u if needed\n", i2c_port); + // if (is_i2c_started(i2c_port)) { + // if ((err = i2c_driver_delete(i2c_port)) != ESP_OK) { + // fprintf(f, "i2c driver delete failed. %s\n", esp_err_to_name(err)); + // nerrors++; + // } + // } + // } + // if (!nerrors) { + // if ((err = i2c_master_driver_initialize(argv[0], &conf)) == ESP_OK) { + // if ((err = i2c_master_driver_install(argv[0])) != ESP_OK) { + // nerrors++; + // } else { + // fprintf(f, "i2c driver successfully started.\n"); + // } + // } else { + // nerrors++; + // } + // } + // if (!nerrors) { + // fprintf(f, "Storing i2c parameters.\n"); + // config_i2c_set(&conf, i2c_port); + // } + // if (!nerrors) { + // fprintf(f, "Done.\n"); + // } + // fflush(f); + // cmd_send_messaging(argv[0], nerrors > 0 ? MESSAGING_ERROR : MESSAGING_INFO, "%s", buf); + // fclose(f); + // FREE_AND_NULL(buf); return nerrors; } @@ -608,31 +534,24 @@ static int do_i2cconfig_cmd(int argc, char** argv) { #if CONFIG_WITH_CONFIG_UI static int do_i2cdump_cmd(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cdump_args); - if (nerrors != 0) { - return 1; - } + if(nerrors != 0) { return 1; } /* Check chip address: "-c" option */ int chip_addr = i2cdump_args.chip_address->ival[0]; /* Check read size: "-s" option */ int size = 1; - if (i2cdump_args.size->count) { - size = i2cdump_args.size->ival[0]; - } + if(i2cdump_args.size->count) { size = i2cdump_args.size->ival[0]; } i2c_port_t loc_i2c_port = i2c_port; - if (i2cset_args.port->count && - i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != ESP_OK) { - return 1; - } + if(i2cset_args.port->count && i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != ESP_OK) { return 1; } - if (size != 1 && size != 2 && size != 4) { + if(size != 1 && size != 2 && size != 4) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Wrong read size. Only support 1,2,4\n"); return 1; } char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f == NULL) { + if(f == NULL) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream.\n"); return 1; } @@ -642,9 +561,9 @@ static int do_i2cdump_cmd(int argc, char** argv) { int32_t block[16]; fprintf(f, "\n 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f" " 0123456789abcdef\r\n"); - for (int i = 0; i < 128; i += 16) { + for(int i = 0; i < 128; i += 16) { fprintf(f, "%02x: ", i); - for (int j = 0; j < 16; j += size) { + for(int j = 0; j < 16; j += size) { fflush(stdout); data_addr = i + j; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); @@ -653,33 +572,29 @@ static int do_i2cdump_cmd(int argc, char** argv) { i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, chip_addr << 1 | READ_BIT, ACK_CHECK_EN); - if (size > 1) { - i2c_master_read(cmd, data, size - 1, ACK_VAL); - } + if(size > 1) { i2c_master_read(cmd, data, size - 1, ACK_VAL); } i2c_master_read_byte(cmd, data + size - 1, NACK_VAL); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(loc_i2c_port, cmd, 50 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - if (ret == ESP_OK) { - for (int k = 0; k < size; k++) { + if(ret == ESP_OK) { + for(int k = 0; k < size; k++) { fprintf(f, "%02x ", data[k]); block[j + k] = data[k]; } } else { - for (int k = 0; k < size; k++) { + for(int k = 0; k < size; k++) { fprintf(f, "XX "); block[j + k] = -1; } } } fprintf(f, " "); - for (int k = 0; k < 16; k++) { - if (block[k] < 0) { - fprintf(f, "X"); - } - if ((block[k] & 0xff) == 0x00 || (block[k] & 0xff) == 0xff) { + for(int k = 0; k < 16; k++) { + if(block[k] < 0) { fprintf(f, "X"); } + if((block[k] & 0xff) == 0x00 || (block[k] & 0xff) == 0xff) { fprintf(f, "."); - } else if ((block[k] & 0xff) < 32 || (block[k] & 0xff) >= 127) { + } else if((block[k] & 0xff) < 32 || (block[k] & 0xff) >= 127) { fprintf(f, "?"); } else { fprintf(f, "%c", block[k] & 0xff); @@ -698,23 +613,16 @@ static int do_i2cdump_cmd(int argc, char** argv) { static int do_i2cset_cmd(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cset_args); - if (nerrors != 0) { - return 1; - } + if(nerrors != 0) { return 1; } /* Check chip address: "-c" option */ int chip_addr = i2cset_args.chip_address->ival[0]; /* Check register address: "-r" option */ int data_addr = 0; - if (i2cset_args.register_address->count) { - data_addr = i2cset_args.register_address->ival[0]; - } + if(i2cset_args.register_address->count) { data_addr = i2cset_args.register_address->ival[0]; } i2c_port_t loc_i2c_port = i2c_port; - if (i2cset_args.port->count && - i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != ESP_OK) { - return 1; - } + if(i2cset_args.port->count && i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != ESP_OK) { return 1; } /* Check data: "-d" option */ int len = i2cset_args.data->count; @@ -722,18 +630,14 @@ static int do_i2cset_cmd(int argc, char** argv) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN); - if (i2cset_args.register_address->count) { - i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN); - } - for (int i = 0; i < len; i++) { - i2c_master_write_byte(cmd, i2cset_args.data->ival[i], ACK_CHECK_EN); - } + if(i2cset_args.register_address->count) { i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN); } + for(int i = 0; i < len; i++) { i2c_master_write_byte(cmd, i2cset_args.data->ival[i], ACK_CHECK_EN); } i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(loc_i2c_port, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - if (ret == ESP_OK) { + if(ret == ESP_OK) { cmd_send_messaging(argv[0], MESSAGING_INFO, "i2c Write OK\n"); - } else if (ret == ESP_ERR_TIMEOUT) { + } else if(ret == ESP_ERR_TIMEOUT) { cmd_send_messaging(argv[0], MESSAGING_WARNING, "i2c Bus is busy\n"); } else { cmd_send_messaging(argv[0], MESSAGING_ERROR, "i2c Read failed\n"); @@ -746,59 +650,47 @@ static int do_i2cset_cmd(int argc, char** argv) { static int do_i2cget_cmd(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cget_args); - if (nerrors != 0) { - return 1; - } + if(nerrors != 0) { return 1; } /* Check chip address: "-c" option */ int chip_addr = i2cget_args.chip_address->ival[0]; /* Check register address: "-r" option */ int data_addr = -1; - if (i2cget_args.register_address->count) { - data_addr = i2cget_args.register_address->ival[0]; - } + if(i2cget_args.register_address->count) { data_addr = i2cget_args.register_address->ival[0]; } /* Check data length: "-l" option */ int len = 1; - if (i2cget_args.data_length->count) { - len = i2cget_args.data_length->ival[0]; - } + if(i2cget_args.data_length->count) { len = i2cget_args.data_length->ival[0]; } i2c_port_t loc_i2c_port = i2cget_args.port->ival[0]; - const sys_i2c_bus*i2c = get_i2c_bus(loc_i2c_port); - #pragma message("TODO: Fix this!") + const sys_i2c_bus* i2c = get_i2c_bus(loc_i2c_port); +#pragma message("TODO: Fix this!") char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f == NULL) { + if(f == NULL) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream.\n"); return 1; } i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); uint8_t* data = malloc_init_external(len); - if (data_addr != -1) { + if(data_addr != -1) { i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN); i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN); i2c_master_start(cmd); } i2c_master_write_byte(cmd, chip_addr << 1 | READ_BIT, ACK_CHECK_EN); - if (len > 1) { - i2c_master_read(cmd, data, len - 1, ACK_VAL); - } + if(len > 1) { i2c_master_read(cmd, data, len - 1, ACK_VAL); } i2c_master_read_byte(cmd, data + len - 1, NACK_VAL); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(loc_i2c_port, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - if (ret == ESP_OK) { - for (int i = 0; i < len; i++) { + if(ret == ESP_OK) { + for(int i = 0; i < len; i++) { fprintf(f, "0x%02x ", data[i]); - if ((i + 1) % 16 == 0) { - fprintf(f, "\r\n"); - } + if((i + 1) % 16 == 0) { fprintf(f, "\r\n"); } } - if (len % 16) { - fprintf(f, "\r\n"); - } - } else if (ret == ESP_ERR_TIMEOUT) { + if(len % 16) { fprintf(f, "\r\n"); } + } else if(ret == ESP_ERR_TIMEOUT) { cmd_send_messaging(argv[0], MESSAGING_WARNING, "i2c Bus is busy\n"); } else { cmd_send_messaging(argv[0], MESSAGING_ERROR, "i2c Read failed\n"); @@ -814,13 +706,13 @@ static int do_i2cget_cmd(int argc, char** argv) { return 0; } esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) { -#ifdef CONFIG_WITH_CONFIG_UI +#ifdef CONFIG_WITH_CONFIG_UI uint8_t matches[128] = {}; -#endif +#endif int last_match = 0; esp_err_t ret = ESP_OK; - if (!GPIO_IS_VALID_GPIO(scl) || !GPIO_IS_VALID_GPIO(sda)) { + if(!GPIO_IS_VALID_GPIO(scl) || !GPIO_IS_VALID_GPIO(sda)) { fprintf(f, "Invalid GPIO. Cannot scan bus\n"); return 1; } @@ -842,12 +734,12 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) { // make sure that we don't have an i2c driver running i2c_driver_delete(i2c_port); ret = i2c_param_config(i2c_port, &i2c_config); - if (ret != ESP_OK) { + if(ret != ESP_OK) { fprintf(f, "I2C Param Config failed %s\n", esp_err_to_name(ret)); return ret; } ret = i2c_driver_install(i2c_port, I2C_MODE_MASTER, false, false, false); - if (ret != ESP_OK) { + if(ret != ESP_OK) { fprintf(f, "I2C driver install failed %s\n", esp_err_to_name(ret)); return ret; } @@ -855,7 +747,7 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) { #ifndef CONFIG_WITH_CONFIG_UI fprintf(f, "\n 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); #endif - for (int i = 0; i < 128; i++) { + for(int i = 0; i < 128; i++) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); @@ -863,15 +755,15 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) { i2c_master_stop(cmd); ret = i2c_master_cmd_begin(i2c_port, cmd, 50 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - if (ret == ESP_OK) { + if(ret == ESP_OK) { #ifndef CONFIG_WITH_CONFIG_UI fprintf(f, "%02x ", i); -#else +#else matches[++last_match - 1] = i; -#endif +#endif } #ifndef CONFIG_WITH_CONFIG_UI - else if (ret == ESP_ERR_TIMEOUT) { + else if(ret == ESP_ERR_TIMEOUT) { fprintf(f, "UU "); } else { fprintf(f, "-- "); @@ -880,12 +772,10 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) { } i2c_driver_delete(i2c_port); - if (last_match) { + if(last_match) { #if CONFIG_WITH_CONFIG_UI fprintf(f, "i2c device detected (names provided by https://i2cdevices.org/addresses).\n"); - for (int i = 0; i < last_match; i++) { - fprintf(f, "%u [%02xh]- %s\n", matches[i], matches[i], i2c_get_description(matches[i])); - } + for(int i = 0; i < last_match; i++) { fprintf(f, "%u [%02xh]- %s\n", matches[i], matches[i], i2c_get_description(matches[i])); } #endif } else { fprintf(f, "No i2c devices found with scl-%d and sda-%d\n", scl, sda); @@ -901,31 +791,30 @@ static int do_i2cdetect_cmd(int argc, char** argv) { #endif esp_err_t ret = ESP_OK; i2c_port_t loc_i2c_port = i2cdetect_args.port->ival[0]; - + // if (i2cset_args.port->count && i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) != // ESP_OK) { return 1; // } - const sys_i2c_bus*i2c = get_i2c_bus(loc_i2c_port); - + const sys_i2c_bus* i2c = get_i2c_bus(loc_i2c_port); uint8_t address; char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f == NULL) { + if(f == NULL) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Unable to open memory stream."); return 1; } - if (!i2c) { + if(!i2c) { fprintf(f, "I2C bus configuration invalid.\r\n"); } else { fprintf(f, "\n 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { + for(int i = 0; i < 128; i += 16) { fprintf(f, "%02x: ", i); - for (int j = 0; j < 16; j++) { + for(int j = 0; j < 16; j++) { address = i + j; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); @@ -933,12 +822,12 @@ static int do_i2cdetect_cmd(int argc, char** argv) { i2c_master_stop(cmd); ret = i2c_master_cmd_begin(loc_i2c_port, cmd, 50 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - if (ret == ESP_OK) { + if(ret == ESP_OK) { fprintf(f, "%02x ", address); -#ifdef CONFIG_WITH_CONFIG_UI +#ifdef CONFIG_WITH_CONFIG_UI matches[++last_match - 1] = address; #endif - } else if (ret == ESP_ERR_TIMEOUT) { + } else if(ret == ESP_ERR_TIMEOUT) { fprintf(f, "UU "); } else { fprintf(f, "-- "); @@ -948,16 +837,15 @@ static int do_i2cdetect_cmd(int argc, char** argv) { fprintf(f, "\r\n"); } #if CONFIG_WITH_CONFIG_UI - if (last_match) { + if(last_match) { fprintf(f, "\r\n-----------------------------------------------------------------------" "-------------" "\r\nDetected the following devices (names provided by " "https://i2cdevices.org/addresses)."); - for (int i = 0; i < last_match; i++) { + for(int i = 0; i < last_match; i++) { // printf("%02x = %s\r\n", matches[i], i2c_get_description(matches[i])); - fprintf(f, "\r\n%u [%02xh]- %s", matches[i], matches[i], - i2c_get_description(matches[i])); + fprintf(f, "\r\n%u [%02xh]- %s", matches[i], matches[i], i2c_get_description(matches[i])); } fprintf(f, "\r\n-----------------------------------------------------------------------" "-------------\r\n"); @@ -972,7 +860,6 @@ static int do_i2cdetect_cmd(int argc, char** argv) { return 0; } - #if CONFIG_WITH_CONFIG_UI static void register_i2c_set_display() { char* supported_drivers = display_get_supported_drivers(); @@ -983,11 +870,9 @@ static void register_i2c_set_display() { i2cdisp_args.reset = arg_int0(NULL, "reset", "", "Reset GPIO"); i2cdisp_args.hflip = arg_lit0(NULL, "hf", "Flip horizontally"); i2cdisp_args.vflip = arg_lit0(NULL, "vf", "Flip vertically"); - i2cdisp_args.driver = - arg_str0("d", "driver", supported_drivers ? supported_drivers : "", "Driver"); + i2cdisp_args.driver = arg_str0("d", "driver", supported_drivers ? supported_drivers : "", "Driver"); i2cdisp_args.cs = arg_int0("b", "cs", "", "SPI Only. CS GPIO (for SPI displays)"); - i2cdisp_args.speed = arg_int0("s", "speed", "", - "SPI Only. Bus Speed (Default 8000000). SPI interface can work up to 26MHz~40MHz"); + i2cdisp_args.speed = arg_int0("s", "speed", "", "SPI Only. Bus Speed (Default 8000000). SPI interface can work up to 26MHz~40MHz"); i2cdisp_args.back = arg_int0("b", "back", "", "Backlight GPIO (if applicable)"); i2cdisp_args.depth = arg_int0("p", "depth", "-1|1|4", "Bit Depth (only for SSD1326 displays)"); i2cdisp_args.type = arg_str0("t", "type", "", "Interface (default I2C)"); @@ -996,66 +881,47 @@ static void register_i2c_set_display() { i2cdisp_args.clear = arg_lit0(NULL, "clear", "clear configuration and return"); i2cdisp_args.mode = arg_int0("m", "mode", "", "SPI Only. Transaction Line Mode (Default 0)"); i2cdisp_args.end = arg_end(8); - const esp_console_cmd_t i2c_set_display = {.command = CFG_TYPE_HW("display"), - .help = desc_display, - .hint = NULL, - .func = &do_i2c_set_display, - .argtable = &i2cdisp_args}; + const esp_console_cmd_t i2c_set_display = { + .command = CFG_TYPE_HW("display"), .help = desc_display, .hint = NULL, .func = &do_i2c_set_display, .argtable = &i2cdisp_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_set_display)); } #endif static void register_i2cdectect(void) { - i2cdetect_args.port = arg_int1(NULL,NULL, "<0|1>", "Specify the i2c port number"); + i2cdetect_args.port = arg_int1(NULL, NULL, "<0|1>", "Specify the i2c port number"); i2cdetect_args.end = arg_end(1); - const esp_console_cmd_t i2cdetect_cmd = {.command = "i2cdetect", - .help = "Scan I2C bus for devices", - .hint = NULL, - .func = &do_i2cdetect_cmd, - .argtable = &i2cdetect_args}; + const esp_console_cmd_t i2cdetect_cmd = { + .command = "i2cdetect", .help = "Scan I2C bus for devices", .hint = NULL, .func = &do_i2cdetect_cmd, .argtable = &i2cdetect_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&i2cdetect_cmd)); } static void register_i2cget(void) { - i2cget_args.chip_address = - arg_int1("c", "chip", "", "Specify the address of the chip on that bus"); - i2cget_args.register_address = arg_int0( - "r", "register", "", "Specify the address on that chip to read from"); - i2cget_args.data_length = - arg_int0("l", "length", "", "Specify the length to read from that data address"); - i2cget_args.port = arg_int1(NULL,NULL, "<0|1>", "Specify the i2c port number"); + i2cget_args.chip_address = arg_int1("c", "chip", "", "Specify the address of the chip on that bus"); + i2cget_args.register_address = arg_int0("r", "register", "", "Specify the address on that chip to read from"); + i2cget_args.data_length = arg_int0("l", "length", "", "Specify the length to read from that data address"); + i2cget_args.port = arg_int1(NULL, NULL, "<0|1>", "Specify the i2c port number"); i2cget_args.end = arg_end(1); - const esp_console_cmd_t i2cget_cmd = {.command = "i2cget", - .help = "Read registers visible through the I2C bus", - .hint = NULL, - .func = &do_i2cget_cmd, - .argtable = &i2cget_args}; + const esp_console_cmd_t i2cget_cmd = { + .command = "i2cget", .help = "Read registers visible through the I2C bus", .hint = NULL, .func = &do_i2cget_cmd, .argtable = &i2cget_args}; cmd_to_json(&i2cget_cmd); ESP_ERROR_CHECK(esp_console_cmd_register(&i2cget_cmd)); } #if CONFIG_WITH_CONFIG_UI static void register_i2cset(void) { - i2cset_args.chip_address = - arg_int1("c", "chip", "", "Specify the address of the chip on that bus"); - i2cset_args.register_address = arg_int0( - "r", "register", "", "Specify the address on that chip to read from"); - i2cset_args.data = - arg_intn(NULL, NULL, "", 0, 256, "Specify the data to write to that data address"); + i2cset_args.chip_address = arg_int1("c", "chip", "", "Specify the address of the chip on that bus"); + i2cset_args.register_address = arg_int0("r", "register", "", "Specify the address on that chip to read from"); + i2cset_args.data = arg_intn(NULL, NULL, "", 0, 256, "Specify the data to write to that data address"); i2cset_args.port = arg_intn("p", "port", "", 0, 1, "Specify the i2c port (0|2)"); i2cset_args.end = arg_end(2); - const esp_console_cmd_t i2cset_cmd = {.command = "i2cset", - .help = "Set registers visible through the I2C bus", - .hint = NULL, - .func = &do_i2cset_cmd, - .argtable = &i2cset_args}; + const esp_console_cmd_t i2cset_cmd = { + .command = "i2cset", .help = "Set registers visible through the I2C bus", .hint = NULL, .func = &do_i2cset_cmd, .argtable = &i2cset_args}; cmd_to_json(&i2cset_cmd); ESP_ERROR_CHECK(esp_console_cmd_register(&i2cset_cmd)); } static void register_i2cdump(void) { - i2cdump_args.chip_address = - arg_int1("c", "chip", "", "Specify the address of the chip on that bus"); + i2cdump_args.chip_address = arg_int1("c", "chip", "", "Specify the address of the chip on that bus"); i2cdump_args.size = arg_int0("s", "size", "", "Specify the size of each read"); i2cdump_args.end = arg_end(3); const esp_console_cmd_t i2cdump_cmd = {.command = "i2cdump", @@ -1071,35 +937,19 @@ static void register_i2cdump(void) { cJSON* i2config_cb() { cJSON* values = cJSON_CreateObject(); const i2c_config_t* i2c = config_i2c_get(&platform->dev.i2c); - if (i2c->scl_io_num > 0) { - cJSON_AddNumberToObject(values, "scl", i2c->scl_io_num); - } - if (i2c->sda_io_num > 0) { - cJSON_AddNumberToObject(values, "sda", i2c->sda_io_num); - } - if (i2c->master.clk_speed > 0) { - cJSON_AddNumberToObject(values, "speed", i2c->master.clk_speed); - } - if (platform->dev.i2c.port-sys_i2c_port_PORT0 >= 0) { - cJSON_AddNumberToObject(values, "port", platform->dev.i2c.port-sys_i2c_port_PORT0); - } + if(i2c->scl_io_num > 0) { cJSON_AddNumberToObject(values, "scl", i2c->scl_io_num); } + if(i2c->sda_io_num > 0) { cJSON_AddNumberToObject(values, "sda", i2c->sda_io_num); } + if(i2c->master.clk_speed > 0) { cJSON_AddNumberToObject(values, "speed", i2c->master.clk_speed); } + if(platform->dev.i2c.port - sys_i2c_port_PORT0 >= 0) { cJSON_AddNumberToObject(values, "port", platform->dev.i2c.port - sys_i2c_port_PORT0); } return values; } cJSON* spiconfig_cb() { cJSON* values = cJSON_CreateObject(); const spi_bus_config_t* spi_config = config_spi_get(NULL); - if (spi_config->mosi_io_num > 0) { - cJSON_AddNumberToObject(values, "data", spi_config->mosi_io_num); - } - if (spi_config->sclk_io_num > 0) { - cJSON_AddNumberToObject(values, "clk", spi_config->sclk_io_num); - } - if (spi_system_dc_gpio > 0) { - cJSON_AddNumberToObject(values, "dc", spi_system_dc_gpio); - } - if (spi_system_host > 0) { - cJSON_AddNumberToObject(values, "host", spi_system_host); - } + if(spi_config->mosi_io_num > 0) { cJSON_AddNumberToObject(values, "data", spi_config->mosi_io_num); } + if(spi_config->sclk_io_num > 0) { cJSON_AddNumberToObject(values, "clk", spi_config->sclk_io_num); } + if(spi_system_dc_gpio > 0) { cJSON_AddNumberToObject(values, "dc", spi_system_dc_gpio); } + if(spi_system_host > 0) { cJSON_AddNumberToObject(values, "host", spi_system_host); } return values; } #if CONFIG_WITH_CONFIG_UI @@ -1111,11 +961,8 @@ static void register_spiconfig(void) { spiconfig_args.dc = arg_int0("c", "dc", "", "DC GPIO"); spiconfig_args.host = arg_int0("h", "host", "1|2", "SPI Host Number"); spiconfig_args.end = arg_end(4); - const esp_console_cmd_t spiconfig_cmd = {.command = CFG_TYPE_HW("spi"), - .help = desc_spiconfig, - .hint = NULL, - .func = &do_spiconfig_cmd, - .argtable = &spiconfig_args}; + const esp_console_cmd_t spiconfig_cmd = { + .command = CFG_TYPE_HW("spi"), .help = desc_spiconfig, .hint = NULL, .func = &do_spiconfig_cmd, .argtable = &spiconfig_args}; cmd_to_json_with_cb(&spiconfig_cmd, &spiconfig_cb); ESP_ERROR_CHECK(esp_console_cmd_register(&spiconfig_cmd)); } @@ -1127,11 +974,8 @@ static void register_i2cconfig(void) { i2cconfig_args.sda = arg_int0("d", "sda", "", "SDA GPIO. e.g. 19"); i2cconfig_args.scl = arg_int0("c", "scl", "", "SCL GPIO. e.g. 18"); i2cconfig_args.end = arg_end(4); - const esp_console_cmd_t i2cconfig_cmd = {.command = CFG_TYPE_HW("i2c"), - .help = desc_i2c, - .hint = NULL, - .func = &do_i2cconfig_cmd, - .argtable = &i2cconfig_args}; + const esp_console_cmd_t i2cconfig_cmd = { + .command = CFG_TYPE_HW("i2c"), .help = desc_i2c, .hint = NULL, .func = &do_i2cconfig_cmd, .argtable = &i2cconfig_args}; cmd_to_json_with_cb(&i2cconfig_cmd, &i2config_cb); ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd)); } diff --git a/components/platform_console/cmd_i2ctools.h b/components/platform_console/cmd_i2ctools.h index c9e858f2..24818582 100644 --- a/components/platform_console/cmd_i2ctools.h +++ b/components/platform_console/cmd_i2ctools.h @@ -14,7 +14,7 @@ extern "C" { #endif void register_i2ctools(void); -esp_err_t cmd_i2ctools_scan_bus(FILE *f,int sda, int scl); +esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl); #ifdef __cplusplus } #endif diff --git a/components/platform_console/cmd_ota.c b/components/platform_console/cmd_ota.c index c42e6fa7..1e1c3c67 100644 --- a/components/platform_console/cmd_ota.c +++ b/components/platform_console/cmd_ota.c @@ -27,27 +27,24 @@ #include "platform_console.h" #include "messaging.h" -static const char * TAG = "ota"; -extern esp_err_t start_ota(const char * bin_url); +static const char* TAG = "ota"; +extern esp_err_t start_ota(const char* bin_url); static struct { - struct arg_str *url; - struct arg_end *end; + struct arg_str* url; + struct arg_end* end; } ota_args; /* 'heap' command prints minumum heap size */ -static int perform_ota_update(int argc, char **argv) -{ - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&ota_args); - if (nerrors != 0) { - return 1; - } +static int perform_ota_update(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&ota_args); + if(nerrors != 0) { return 1; } - const char *url = ota_args.url->sval[0]; + const char* url = ota_args.url->sval[0]; - esp_err_t err=ESP_OK; + esp_err_t err = ESP_OK; ESP_LOGI(TAG, "Starting ota: %s", url); start_ota(url); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "%s", esp_err_to_name(err)); return 1; } @@ -55,20 +52,10 @@ static int perform_ota_update(int argc, char **argv) return 0; } - void register_ota_cmd() -{ - ota_args.url= arg_str1(NULL, NULL, "", "url of the binary app file"); - ota_args.end = arg_end(2); +void register_ota_cmd() { + ota_args.url = arg_str1(NULL, NULL, "", "url of the binary app file"); + ota_args.end = arg_end(2); - const esp_console_cmd_t cmd = { - .command = "update", - .help = "Update from URL", - .hint = NULL, - .func = &perform_ota_update, - .argtable = &ota_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); + const esp_console_cmd_t cmd = {.command = "update", .help = "Update from URL", .hint = NULL, .func = &perform_ota_update, .argtable = &ota_args}; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } - - - diff --git a/components/platform_console/cmd_ota.h b/components/platform_console/cmd_ota.h index 7e00647a..92f7f59e 100644 --- a/components/platform_console/cmd_ota.h +++ b/components/platform_console/cmd_ota.h @@ -13,7 +13,7 @@ extern "C" { #endif // Register system functions - void register_ota_cmd(); +void register_ota_cmd(); #ifdef __cplusplus } #endif diff --git a/components/platform_console/cmd_system.c b/components/platform_console/cmd_system.c index 3c5228e1..2bf1197e 100644 --- a/components/platform_console/cmd_system.c +++ b/components/platform_console/cmd_system.c @@ -37,7 +37,6 @@ #include #include "tools_spiffs_utils.h" - #if defined(CONFIG_WITH_METRICS) #include "Metrics.h" #endif @@ -66,7 +65,7 @@ EXT_RAM_ATTR static struct { } names_args; EXT_RAM_ATTR static struct { struct arg_str* name; - struct arg_lit*reset; + struct arg_lit* reset; struct arg_end* end; } target_args; @@ -114,9 +113,7 @@ static void register_tasks(); extern BaseType_t network_manager_task; FILE* system_open_memstream(const char* cmdname, char** buf, size_t* buf_size) { FILE* f = open_memstream(buf, buf_size); - if (f == NULL) { - cmd_send_messaging(cmdname, MESSAGING_ERROR, "Unable to open memory stream."); - } + if(f == NULL) { cmd_send_messaging(cmdname, MESSAGING_ERROR, "Unable to open memory stream."); } return f; } @@ -133,12 +130,9 @@ static int get_version(int argc, char** argv) { "\tcores:%d\r\n" "\tfeature:%s%s%s%s%d%s\r\n" "\trevision number:%d\r\n", - esp_get_idf_version(), info.model == CHIP_ESP32 ? "ESP32" : "Unknow", info.cores, - info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", - info.features & CHIP_FEATURE_BLE ? "/BLE" : "", - info.features & CHIP_FEATURE_BT ? "/BT" : "", - info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:", - flash_size / (1024 * 1024), " MB", info.revision); + esp_get_idf_version(), info.model == CHIP_ESP32 ? "ESP32" : "Unknow", info.cores, info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "", + info.features & CHIP_FEATURE_BLE ? "/BLE" : "", info.features & CHIP_FEATURE_BT ? "/BT" : "", + info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:", flash_size / (1024 * 1024), " MB", info.revision); return 0; } @@ -255,14 +249,11 @@ static int heap_size(int argc, char** argv) { "External | %7zu | %7zu | %7zu | %7zu | %7zu | %4.1f%% | %4.1f%%\n" "DMA | %7zu | %7zu | %7zu | %7zu | %7zu | %4.1f%% | %4.1f%%", total_internal, allocated_internal, heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), free_internal, - (allocated_internal * 100.0) / total_internal, (free_internal * 100.0) / total_internal, - total_external, allocated_external, heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), free_external, - (allocated_external * 100.0) / total_external, (free_external * 100.0) / total_external, - total_dma, allocated_dma, heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), - heap_caps_get_largest_free_block(MALLOC_CAP_DMA), free_dma, - (allocated_dma * 100.0) / total_dma, (free_dma * 100.0) / total_dma); + heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), free_internal, (allocated_internal * 100.0) / total_internal, + (free_internal * 100.0) / total_internal, total_external, allocated_external, heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), free_external, (allocated_external * 100.0) / total_external, + (free_external * 100.0) / total_external, total_dma, allocated_dma, heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), + heap_caps_get_largest_free_block(MALLOC_CAP_DMA), free_dma, (allocated_dma * 100.0) / total_dma, (free_dma * 100.0) / total_dma); return 0; } @@ -382,7 +373,7 @@ int set_squeezelite_player_name(FILE* f, const char* name) { static int do_cat(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&ls_args); - if (nerrors != 0) { + if(nerrors != 0) { arg_print_errors(stderr, ls_args.end, argv[0]); return 1; } @@ -394,7 +385,7 @@ static int do_cat(int argc, char** argv) { } static int do_ls(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&ls_args); - if (nerrors != 0) { + if(nerrors != 0) { arg_print_errors(stderr, ls_args.end, argv[0]); return 1; } @@ -419,14 +410,14 @@ static int do_ls(int argc, char** argv) { // } static int do_erase(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&erase_args); - if (nerrors != 0) { + if(nerrors != 0) { arg_print_errors(stderr, erase_args.end, argv[0]); return 1; } // Erase file at the provided path const char* path = erase_args.path->sval[0]; - if (!erase_path(path, true)) { + if(!erase_path(path, true)) { // Handle error if erase_path returns false // For example, log an error message fprintf(stderr, "Failed to erase file at path: %s\n", path); @@ -441,15 +432,13 @@ static int do_erase(int argc, char** argv) { static int do_set_target(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&target_args); - if (nerrors != 0) { + if(nerrors != 0) { return 1; } + if(target_args.name->count <= 0) { + ESP_LOGW(TAG, "Target name must be specified. Current target: %s", STR_OR_ALT(platform->target, "N/A")); return 1; } - if (target_args.name->count <= 0) { - ESP_LOGW(TAG, "Target name must be specified. Current target: %s", - STR_OR_ALT(platform->target, "N/A")); - return 1; - } - network_async_callback((void*)target_args.name->sval[0], (network_manager_cb_t)(target_args.reset->count>0?config_set_target_reset:config_set_target_no_reset)); + network_async_callback((void*)target_args.name->sval[0], + (network_manager_cb_t)(target_args.reset->count > 0 ? config_set_target_reset : config_set_target_no_reset)); return nerrors; } @@ -457,11 +446,8 @@ static int do_set_target(int argc, char** argv) { static int do_reset_config(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&reset_config_args); - if (nerrors != 0) { - return 1; - } - if (reset_config_args.confirm->count <= 0 || - strcmp(reset_config_args.confirm->sval[0], "YES") != 0) { + if(nerrors != 0) { return 1; } + if(reset_config_args.confirm->count <= 0 || strcmp(reset_config_args.confirm->sval[0], "YES") != 0) { ESP_LOGW(TAG, "Confirmation needed. Call reset_config YES to confirm"); return 1; } @@ -472,8 +458,7 @@ static int do_reset_config(int argc, char** argv) { } static void register_reset_config() { - reset_config_args.confirm = - arg_str0(NULL, NULL, "YES", "To execute the reset, confirm with YES"); + reset_config_args.confirm = arg_str0(NULL, NULL, "YES", "To execute the reset, confirm with YES"); reset_config_args.end = arg_end(1); const esp_console_cmd_t reset_config = {.command = "reset_config", @@ -488,51 +473,40 @@ static void register_reset_config() { static int setdevicename(int argc, char** argv) { bool changed = false; int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&names_args); - if (nerrors != 0) { - return 1; - } - if (names_args.device->count > 0) { - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_device_tag, - &platform->names, names_args.device->sval[0]); + if(nerrors != 0) { return 1; } + if(names_args.device->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_device_tag, &platform->names, names_args.device->sval[0]); } else { ESP_LOGE(TAG, "Device name must be specified"); return 1; } - if (names_args.airplay->count > 0) { - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_airplay_tag, - &platform->names, names_args.airplay->sval[0]); + if(names_args.airplay->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_airplay_tag, &platform->names, names_args.airplay->sval[0]); } - if (names_args.bluetooth->count > 0) { - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, - &platform->names, names_args.bluetooth->sval[0]); + if(names_args.bluetooth->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, &platform->names, names_args.bluetooth->sval[0]); } - if (names_args.spotify->count > 0) { - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_spotify_tag, - &platform->names, names_args.spotify->sval[0]); + if(names_args.spotify->count > 0) { + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_spotify_tag, &platform->names, names_args.spotify->sval[0]); } - if (names_args.squeezelite->count > 0) { - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, - &platform->names, names_args.squeezelite->sval[0]); + if(names_args.squeezelite->count > 0) { + changed = + changed | system_set_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, &platform->names, names_args.squeezelite->sval[0]); } - if (names_args.wifi_ap_name->count > 0) { - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, - &platform->names, names_args.wifi_ap_name->sval[0]); + if(names_args.wifi_ap_name->count > 0) { + changed = + changed | system_set_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, &platform->names, names_args.wifi_ap_name->sval[0]); } - if (names_args.all->count > 0) { + if(names_args.all->count > 0) { ESP_LOGI(TAG, "Setting all names to %s", platform->names.device); - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_airplay_tag, - &platform->names, platform->names.device); - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, - &platform->names, platform->names.device); - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_spotify_tag, - &platform->names, platform->names.device); - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, - &platform->names, platform->names.device); - changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, - &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_airplay_tag, &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_bluetooth_tag, &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_spotify_tag, &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_squeezelite_tag, &platform->names, platform->names.device); + changed = changed | system_set_string(&sys_names_config_msg, sys_names_config_wifi_ap_name_tag, &platform->names, platform->names.device); } - if (changed) { + if(changed) { ESP_LOGI(TAG, "Found change(s). Saving"); config_raise_changed(false); } else { @@ -575,7 +549,7 @@ static void register_dump_config() { } static void register_settarget() { target_args.name = arg_str0(NULL, NULL, STR_OR_BLANK(platform->target), "New Target Name"); - target_args.reset = arg_lit0("r","reset","Full reset before setting target (recommended)"); + target_args.reset = arg_lit0("r", "reset", "Full reset before setting target (recommended)"); target_args.end = arg_end(1); const esp_console_cmd_t set_target = {.command = "target", .help = "Set the device target Name (SqueezeAMP, SqueezeIO, Muse, etc. )", @@ -605,22 +579,15 @@ static void register_settarget() { static void register_ls() { ls_args.path = arg_str1(NULL, NULL, "", "Path to list files"); ls_args.end = arg_end(1); - const esp_console_cmd_t ls_cmd = {.command = "ls", - .help = "List files in a path", - .hint = NULL, - .func = &do_ls, - .argtable = &ls_args}; + const esp_console_cmd_t ls_cmd = {.command = "ls", .help = "List files in a path", .hint = NULL, .func = &do_ls, .argtable = &ls_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&ls_cmd)); } static void register_cat() { ls_args.path = arg_str1(NULL, NULL, "", "File name to cat"); ls_args.end = arg_end(1); - const esp_console_cmd_t cat_cmd = {.command = "cat", - .help = "Dumps the content of a file to the console", - .hint = NULL, - .func = &do_cat, - .argtable = &ls_args}; + const esp_console_cmd_t cat_cmd = { + .command = "cat", .help = "Dumps the content of a file to the console", .hint = NULL, .func = &do_cat, .argtable = &ls_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&cat_cmd)); } @@ -628,11 +595,8 @@ static void register_cat() { static void register_erase() { erase_args.path = arg_str1(NULL, NULL, "", "Path of the file(s) to erase"); erase_args.end = arg_end(1); - const esp_console_cmd_t erase_cmd = {.command = "erase", - .help = "Erase file(s) at a given path", - .hint = NULL, - .func = &do_erase, - .argtable = &erase_args}; + const esp_console_cmd_t erase_cmd = { + .command = "erase", .help = "Erase file(s) at a given path", .hint = NULL, .func = &do_erase, .argtable = &erase_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&erase_cmd)); } @@ -643,16 +607,12 @@ static void register_setdevicename() { names_args.airplay = arg_str0("a", "airplay", default_host_name, "New Airplay Device Name"); names_args.bluetooth = arg_str0("b", "bt", default_host_name, "New Bluetooth Device Name"); names_args.spotify = arg_str0("s", "spotify", default_host_name, "New Spotify Device Name"); - names_args.squeezelite = - arg_str0("l", "squeezelite", default_host_name, "New Squeezelite Player Name"); + names_args.squeezelite = arg_str0("l", "squeezelite", default_host_name, "New Squeezelite Player Name"); names_args.wifi_ap_name = arg_str0("w", "wifiap", default_host_name, "New Wifi AP Name"); names_args.all = arg_lit0(NULL, "all", "Set all names to device name"); names_args.end = arg_end(2); - const esp_console_cmd_t set_name = {.command = CFG_TYPE_SYST("name"), - .help = "Device Name", - .hint = NULL, - .func = &setdevicename, - .argtable = &names_args}; + const esp_console_cmd_t set_name = { + .command = CFG_TYPE_SYST("name"), .help = "Device Name", .hint = NULL, .func = &setdevicename, .argtable = &names_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&set_name)); } @@ -662,9 +622,8 @@ static void register_setdevicename() { static int tasks_info(int argc, char** argv) { const size_t bytes_per_task = 40; /* see vTaskList description */ char* task_list_buffer = malloc_init_external(uxTaskGetNumberOfTasks() * bytes_per_task); - if (task_list_buffer == NULL) { - cmd_send_messaging( - argv[0], MESSAGING_ERROR, "failed to allocate buffer for vTaskList output"); + if(task_list_buffer == NULL) { + cmd_send_messaging(argv[0], MESSAGING_ERROR, "failed to allocate buffer for vTaskList output"); return 1; } cmd_send_messaging(argv[0], MESSAGING_INFO, @@ -703,31 +662,27 @@ static struct { static int deep_sleep(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&deep_sleep_args); - if (nerrors != 0) { - return 1; - } - if (deep_sleep_args.wakeup_time->count) { + if(nerrors != 0) { return 1; } + if(deep_sleep_args.wakeup_time->count) { uint64_t timeout = 1000ULL * deep_sleep_args.wakeup_time->ival[0]; - cmd_send_messaging( - argv[0], MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(timeout)); } - if (deep_sleep_args.wakeup_gpio_num->count) { + if(deep_sleep_args.wakeup_gpio_num->count) { int io_num = deep_sleep_args.wakeup_gpio_num->ival[0]; - if (!rtc_gpio_is_valid_gpio(io_num)) { + if(!rtc_gpio_is_valid_gpio(io_num)) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "GPIO %d is not an RTC IO", io_num); return 1; } int level = 0; - if (deep_sleep_args.wakeup_gpio_level->count) { + if(deep_sleep_args.wakeup_gpio_level->count) { level = deep_sleep_args.wakeup_gpio_level->ival[0]; - if (level != 0 && level != 1) { + if(level != 0 && level != 1) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Invalid wakeup level: %d", level); return 1; } } - cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", - io_num, level ? "HIGH" : "LOW"); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", io_num, level ? "HIGH" : "LOW"); ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(1ULL << io_num, level)); } @@ -738,17 +693,12 @@ static int deep_sleep(int argc, char** argv) { static void register_deep_sleep() { deep_sleep_args.wakeup_time = arg_int0("t", "time", "", "Wake up time, ms"); - deep_sleep_args.wakeup_gpio_num = - arg_int0(NULL, "io", "", "If specified, wakeup using GPIO with given number"); - deep_sleep_args.wakeup_gpio_level = - arg_int0(NULL, "io_level", "<0|1>", "GPIO level to trigger wakeup"); + deep_sleep_args.wakeup_gpio_num = arg_int0(NULL, "io", "", "If specified, wakeup using GPIO with given number"); + deep_sleep_args.wakeup_gpio_level = arg_int0(NULL, "io_level", "<0|1>", "GPIO level to trigger wakeup"); deep_sleep_args.end = arg_end(3); - const esp_console_cmd_t cmd = {.command = "deep_sleep", - .help = "Enter deep sleep mode. ", - .hint = NULL, - .func = &deep_sleep, - .argtable = &deep_sleep_args}; + const esp_console_cmd_t cmd = { + .command = "deep_sleep", .help = "Enter deep sleep mode. ", .hint = NULL, .func = &deep_sleep, .argtable = &deep_sleep_args}; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } #endif @@ -886,41 +836,32 @@ static struct { static int light_sleep(int argc, char** argv) { int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&light_sleep_args); - if (nerrors != 0) { - return 1; - } + if(nerrors != 0) { return 1; } esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); - if (light_sleep_args.wakeup_time->count) { + if(light_sleep_args.wakeup_time->count) { uint64_t timeout = 1000ULL * light_sleep_args.wakeup_time->ival[0]; - cmd_send_messaging( - argv[0], MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling timer wakeup, timeout=%lluus", timeout); ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(timeout)); } int io_count = light_sleep_args.wakeup_gpio_num->count; - if (io_count != light_sleep_args.wakeup_gpio_level->count) { - cmd_send_messaging( - argv[0], MESSAGING_INFO, "Should have same number of 'io' and 'io_level' arguments"); + if(io_count != light_sleep_args.wakeup_gpio_level->count) { + cmd_send_messaging(argv[0], MESSAGING_INFO, "Should have same number of 'io' and 'io_level' arguments"); return 1; } - for (int i = 0; i < io_count; ++i) { + for(int i = 0; i < io_count; ++i) { int io_num = light_sleep_args.wakeup_gpio_num->ival[i]; int level = light_sleep_args.wakeup_gpio_level->ival[i]; - if (level != 0 && level != 1) { + if(level != 0 && level != 1) { cmd_send_messaging(argv[0], MESSAGING_ERROR, "Invalid wakeup level: %d", level); return 1; } - cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", - io_num, level ? "HIGH" : "LOW"); + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling wakeup on GPIO%d, wakeup on %s level", io_num, level ? "HIGH" : "LOW"); - ESP_ERROR_CHECK( - gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL)); + ESP_ERROR_CHECK(gpio_wakeup_enable(io_num, level ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL)); } - if (io_count > 0) { - ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup()); - } - if (CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) { - cmd_send_messaging( - argv[0], MESSAGING_INFO, "Enabling UART wakeup (press ENTER to exit light sleep)"); + if(io_count > 0) { ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup()); } + if(CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) { + cmd_send_messaging(argv[0], MESSAGING_INFO, "Enabling UART wakeup (press ENTER to exit light sleep)"); ESP_ERROR_CHECK(uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3)); ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM)); } @@ -929,7 +870,7 @@ static int light_sleep(int argc, char** argv) { esp_light_sleep_start(); esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); const char* cause_str; - switch (cause) { + switch(cause) { case ESP_SLEEP_WAKEUP_GPIO: cause_str = "GPIO"; break; @@ -949,10 +890,8 @@ static int light_sleep(int argc, char** argv) { static void register_light_sleep() { light_sleep_args.wakeup_time = arg_int0("t", "time", "", "Wake up time, ms"); - light_sleep_args.wakeup_gpio_num = - arg_intn(NULL, "io", "", 0, 8, "If specified, wakeup using GPIO with given number"); - light_sleep_args.wakeup_gpio_level = - arg_intn(NULL, "io_level", "<0|1>", 0, 8, "GPIO level to trigger wakeup"); + light_sleep_args.wakeup_gpio_num = arg_intn(NULL, "io", "", 0, 8, "If specified, wakeup using GPIO with given number"); + light_sleep_args.wakeup_gpio_level = arg_intn(NULL, "io_level", "<0|1>", 0, 8, "GPIO level to trigger wakeup"); light_sleep_args.end = arg_end(3); const esp_console_cmd_t cmd = {.command = "light_sleep", diff --git a/components/platform_console/cmd_system.h b/components/platform_console/cmd_system.h index c13471c7..fd3fd11d 100644 --- a/components/platform_console/cmd_system.h +++ b/components/platform_console/cmd_system.h @@ -15,7 +15,7 @@ extern "C" { // Register system functions void register_system(); -FILE * system_open_memstream(const char * cmdname,char **buf,size_t *buf_size); +FILE* system_open_memstream(const char* cmdname, char** buf, size_t* buf_size); #ifdef __cplusplus } #endif diff --git a/components/platform_console/cmd_wifi.c b/components/platform_console/cmd_wifi.c index c828de9c..b196eb5a 100644 --- a/components/platform_console/cmd_wifi.c +++ b/components/platform_console/cmd_wifi.c @@ -40,81 +40,69 @@ extern bool bypass_network_manager; // To enable wifi configuration from the command line, uncomment the line below // define WIFI_CMDLINE 1 - extern EventGroupHandle_t network_event_group; extern const int CONNECTED_BIT; //static const char * TAG = "cmd_wifi"; /** Arguments used by 'join' function */ static struct { - struct arg_int *timeout; - struct arg_str *ssid; - struct arg_str *password; - struct arg_end *end; + struct arg_int* timeout; + struct arg_str* ssid; + struct arg_str* password; + struct arg_end* end; } join_args; - - - - -static void event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) -{ - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - led_blink_pushed(LED_GREEN, 250, 250); +static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { + if(event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + led_blink_pushed(LED_GREEN, 250, 250); esp_wifi_connect(); xEventGroupClearBits(network_event_group, CONNECTED_BIT); - } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { - led_unpush(LED_GREEN); + } else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + led_unpush(LED_GREEN); xEventGroupSetBits(network_event_group, CONNECTED_BIT); } } -static void initialise_wifi(void) -{ +static void initialise_wifi(void) { static bool initialized = false; - if (initialized) { - return; - } + if(initialized) { return; } esp_netif_init(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &event_handler, NULL) ); - ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) ); - ESP_ERROR_CHECK( esp_wifi_start() ); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); + ESP_ERROR_CHECK(esp_wifi_start()); initialized = true; - led_blink(LED_GREEN, 250, 250); + led_blink(LED_GREEN, 250, 250); } -static void wifi_join(TimerHandle_t timer) -{ +static void wifi_join(TimerHandle_t timer) { (void)timer; - const char *ssid = join_args.ssid->sval[0]; - const char *pass = join_args.password->sval[0]; - int timeout_ms = join_args.timeout->ival[0]; - + const char* ssid = join_args.ssid->sval[0]; + const char* pass = join_args.password->sval[0]; + int timeout_ms = join_args.timeout->ival[0]; + initialise_wifi(); - wifi_config_t wifi_config = { 0 }; - strncpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); - wifi_config.sta.ssid[sizeof(wifi_config.sta.ssid) - 1] = '\0'; - if (pass) { - strncpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password)); - wifi_config.sta.password[sizeof(wifi_config.sta.password) - 1] = '\0'; + wifi_config_t wifi_config = {0}; + strncpy((char*)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); + wifi_config.sta.ssid[sizeof(wifi_config.sta.ssid) - 1] = '\0'; + if(pass) { + strncpy((char*)wifi_config.sta.password, pass, sizeof(wifi_config.sta.password)); + wifi_config.sta.password[sizeof(wifi_config.sta.password) - 1] = '\0'; } - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_connect() ); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_connect()); - int bits = xEventGroupWaitBits(network_event_group, CONNECTED_BIT, - pdFALSE, pdTRUE, timeout_ms / portTICK_PERIOD_MS); - - if (bits & CONNECTED_BIT) { - ESP_LOGI(__func__, "Connected"); + int bits = xEventGroupWaitBits(network_event_group, CONNECTED_BIT, pdFALSE, pdTRUE, timeout_ms / portTICK_PERIOD_MS); + + if(bits & CONNECTED_BIT) { + ESP_LOGI(__func__, "Connected"); } else { ESP_LOGW(__func__, "Connection timed out"); - } + } } //static int set_auto_connect(int argc, char **argv) @@ -143,48 +131,33 @@ static void wifi_join(TimerHandle_t timer) // return 0; //} -static int connect(int argc, char **argv) -{ - int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&join_args); - if (nerrors != 0) { - return 1; - } - ESP_LOGI(__func__, "Connecting to '%s'", - join_args.ssid->sval[0]); +static int connect(int argc, char** argv) { + int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&join_args); + if(nerrors != 0) { return 1; } + ESP_LOGI(__func__, "Connecting to '%s'", join_args.ssid->sval[0]); /* set default value*/ - if (join_args.timeout->count == 0) { - join_args.timeout->ival[0] = JOIN_TIMEOUT_MS; - } + if(join_args.timeout->count == 0) { join_args.timeout->ival[0] = JOIN_TIMEOUT_MS; } - // need to use that trick to make sure we use internal stack - xTimerStart(xTimerCreate("wifi_join", 1, pdFALSE, NULL, wifi_join), portMAX_DELAY); + // need to use that trick to make sure we use internal stack + xTimerStart(xTimerCreate("wifi_join", 1, pdFALSE, NULL, wifi_join), portMAX_DELAY); return 0; } -void register_wifi_join() -{ +void register_wifi_join() { join_args.timeout = arg_int0(NULL, "timeout", "", "Connection timeout, ms"); join_args.ssid = arg_str1(NULL, NULL, "", "SSID of AP"); join_args.password = arg_str0(NULL, NULL, "", "PSK of AP"); join_args.end = arg_end(2); const esp_console_cmd_t join_cmd = { - .command = "join", - .help = "Join WiFi AP as a station", - .hint = NULL, - .func = &connect, - .argtable = &join_args - }; - ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) ); + .command = "join", .help = "Join WiFi AP as a station", .hint = NULL, .func = &connect, .argtable = &join_args}; + ESP_ERROR_CHECK(esp_console_cmd_register(&join_cmd)); } -void register_wifi() -{ - #ifdef WIFI_CMDLINE +void register_wifi() { +#ifdef WIFI_CMDLINE register_wifi_join(); - if(bypass_network_manager){ - initialise_wifi(); - } - #endif + if(bypass_network_manager) { initialise_wifi(); } +#endif } diff --git a/components/platform_console/platform_console.c b/components/platform_console/platform_console.c index 5982eff8..93839233 100644 --- a/components/platform_console/platform_console.c +++ b/components/platform_console/platform_console.c @@ -64,11 +64,11 @@ const char* recovery_prompt = LOG_COLOR_E "recovery-squeezelite-esp32> " LOG_RES #define HISTORY_PATH MOUNT_PATH "/history.txt" static esp_err_t run_command(char* line); #define ADD_TO_JSON(o, t, n) \ - if (t->n) cJSON_AddStringToObject(o, QUOTE(n), t->n); + if(t->n) cJSON_AddStringToObject(o, QUOTE(n), t->n); #define ADD_PARMS_TO_CMD(o, t, n) \ { \ cJSON* parms = ParmsToJSON(&t.n->hdr); \ - if (parms) cJSON_AddItemToObject(o, QUOTE(n), parms); \ + if(parms) cJSON_AddItemToObject(o, QUOTE(n), parms); \ } cJSON* cmdList; cJSON* values_fn_list; @@ -81,13 +81,11 @@ cJSON* get_cmd_list() { cJSON_ArrayForEach(element, cmdList) { cJSON* name = cJSON_GetObjectItem(element, "name"); cJSON* vals_fn = cJSON_GetObjectItem(values_fn_list, cJSON_GetStringValue(name)); - if (vals_fn != NULL) { + if(vals_fn != NULL) { parm_values_fn_t* parm_values_fn = (parm_values_fn_t*)strtoul(cJSON_GetStringValue(vals_fn), NULL, 16); ; - if (parm_values_fn) { - cJSON_AddItemToObject(values, cJSON_GetStringValue(name), parm_values_fn()); - } + if(parm_values_fn) { cJSON_AddItemToObject(values, cJSON_GetStringValue(name), parm_values_fn()); } } } return list; @@ -95,7 +93,7 @@ cJSON* get_cmd_list() { void console_set_bool_parameter(cJSON* root, char* nvs_name, struct arg_lit* arg) { char* p = NULL; bool enabled = false; - if (!root) { + if(!root) { ESP_LOGE(TAG, "Invalid json parameter. Cannot set %s from %s", arg->hdr.longopts ? arg->hdr.longopts : arg->hdr.glossary, nvs_name); return; } @@ -112,20 +110,18 @@ void console_set_bool_parameter(cJSON* root, char* nvs_name, struct arg_lit* arg // TODO: Add support for the commented code } struct arg_end* getParmsEnd(struct arg_hdr** argtable) { - if (!argtable) return NULL; + if(!argtable) return NULL; struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex = 0; - while (!(table[tabindex]->flag & ARG_TERMINATOR)) { - tabindex++; - } + while(!(table[tabindex]->flag & ARG_TERMINATOR)) { tabindex++; } return (struct arg_end*)table[tabindex]; } cJSON* ParmsToJSON(struct arg_hdr** argtable) { - if (!argtable) return NULL; + if(!argtable) return NULL; cJSON* arg_list = cJSON_CreateArray(); struct arg_hdr** table = (struct arg_hdr**)argtable; int tabindex = 0; - while (!(table[tabindex]->flag & ARG_TERMINATOR)) { + while(!(table[tabindex]->flag & ARG_TERMINATOR)) { cJSON* entry = cJSON_CreateObject(); ADD_TO_JSON(entry, table[tabindex], datatype); ADD_TO_JSON(entry, table[tabindex], glossary); @@ -149,40 +145,30 @@ cJSON* ParmsToJSON(struct arg_hdr** argtable) { esp_err_t cmd_to_json(const esp_console_cmd_t* cmd) { return cmd_to_json_with_cb(cmd, NULL); } esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t* cmd, parm_values_fn_t parm_values_fn) { - if (!cmdList) { - cmdList = cJSON_CreateArray(); - } - if (!values_fn_list) { - values_fn_list = cJSON_CreateObject(); - } + if(!cmdList) { cmdList = cJSON_CreateArray(); } + if(!values_fn_list) { values_fn_list = cJSON_CreateObject(); } - if (cmd->command == NULL) { - return ESP_ERR_INVALID_ARG; - } - if (strchr(cmd->command, ' ') != NULL) { - return ESP_ERR_INVALID_ARG; - } + if(cmd->command == NULL) { return ESP_ERR_INVALID_ARG; } + if(strchr(cmd->command, ' ') != NULL) { return ESP_ERR_INVALID_ARG; } cJSON* jsoncmd = cJSON_CreateObject(); ADD_TO_JSON(jsoncmd, cmd, help); ADD_TO_JSON(jsoncmd, cmd, hint); - if (parm_values_fn) { + if(parm_values_fn) { char addr[11] = {0}; snprintf(addr, sizeof(addr), "%lx", (unsigned long)parm_values_fn); cJSON_AddStringToObject(values_fn_list, cmd->command, addr); } cJSON_AddBoolToObject(jsoncmd, "hascb", parm_values_fn != NULL); - if (cmd->argtable) { - cJSON_AddItemToObject(jsoncmd, "argtable", ParmsToJSON(cmd->argtable)); - } - if (cmd->hint) { + if(cmd->argtable) { cJSON_AddItemToObject(jsoncmd, "argtable", ParmsToJSON(cmd->argtable)); } + if(cmd->hint) { cJSON_AddStringToObject(jsoncmd, "hint", cmd->hint); - } else if (cmd->argtable) { + } else if(cmd->argtable) { /* Generate hint based on cmd->argtable */ char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f != NULL) { + if(f != NULL) { arg_print_syntax(f, cmd->argtable, NULL); fflush(f); fclose(f); @@ -192,7 +178,7 @@ esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t* cmd, parm_values_fn_t par } cJSON_AddStringToObject(jsoncmd, "name", cmd->command); char* b = cJSON_Print(jsoncmd); - if (b) { + if(b) { ESP_LOGD(TAG, "Adding command table %s", b); free(b); } @@ -202,11 +188,11 @@ esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t* cmd, parm_values_fn_t par int arg_parse_msg(int argc, char** argv, struct arg_hdr** args) { int nerrors = arg_parse(argc, argv, (void**)args); - if (nerrors != 0) { + if(nerrors != 0) { char* buf = NULL; size_t buf_size = 0; FILE* f = open_memstream(&buf, &buf_size); - if (f != NULL) { + if(f != NULL) { arg_print_errors(f, getParmsEnd(args), argv[0]); fflush(f); cmd_send_messaging(argv[0], MESSAGING_ERROR, "%s", buf); @@ -219,34 +205,32 @@ int arg_parse_msg(int argc, char** argv, struct arg_hdr** args) { static ssize_t stdin_read(int fd, void* data, size_t size) { size_t bytes = -1; static size_t remain = 0; - if (remain > 0) { + if(remain > 0) { bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, data, size < remain ? size : remain, 0); remain -= bytes; - for (int i = 0; i < bytes; i++) - if (((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; - return bytes; + for(int i = 0; i < bytes; i++) + if(((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; + return bytes; } - while (1) { + while(1) { QueueSetMemberHandle_t activated = xQueueSelectFromSet(stdin_redir.queue_set, portMAX_DELAY); - if (activated == uart_queue) { + if(activated == uart_queue) { uart_event_t event; xQueueReceive(uart_queue, &event, 0); - if (event.type == UART_DATA) { + if(event.type == UART_DATA) { bytes = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, data, size < event.size ? size : event.size, 0); // we have to do our own line ending translation here - for (int i = 0; i < bytes; i++) - if (((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; - if (event.size > bytes) { - remain = event.size - bytes; - } + for(int i = 0; i < bytes; i++) + if(((char*)data)[i] == '\r') ((char*)data)[i] = '\n'; + if(event.size > bytes) { remain = event.size - bytes; } break; } - } else if (xRingbufferCanRead(stdin_redir.handle, activated)) { + } else if(xRingbufferCanRead(stdin_redir.handle, activated)) { char* p = xRingbufferReceiveUpTo(stdin_redir.handle, &bytes, 0, size); // we might receive strings, replace null by \n - for (int i = 0; i < bytes; i++) - if (p[i] == '\0' || p[i] == '\r') p[i] = '\n'; + for(int i = 0; i < bytes; i++) + if(p[i] == '\0' || p[i] == '\r') p[i] = '\n'; memcpy(data, p, bytes); vRingbufferReturnItem(stdin_redir.handle, p); xRingbufferPrintInfo(stdin_redir.handle); @@ -300,8 +284,7 @@ void initialize_console() { setvbuf(stdin, NULL, _IONBF, 0); /* Initialize the console */ - esp_console_config_t console_config = { - .max_cmdline_args = 28, + esp_console_config_t console_config = {.max_cmdline_args = 28, .max_cmdline_length = 600, #if CONFIG_LOG_COLORS .hint_color = atoi(LOG_COLOR_CYAN) @@ -321,7 +304,6 @@ void initialize_console() { /* Set command history size */ linenoiseHistorySetMaxLen(100); - } bool console_push(const char* data, size_t size) { return xRingbufferSend(stdin_redir.handle, data, size, pdMS_TO_TICKS(100)) == pdPASS; } @@ -334,13 +316,11 @@ void console_start() { register_config_cmd(); register_wifi(); - if (is_recovery_running) { - register_ota_cmd(); - } + if(is_recovery_running) { register_ota_cmd(); } register_i2ctools(); printf("\n"); - if (is_recovery_running) { + if(is_recovery_running) { printf("****************************************************************\n" "RECOVERY APPLICATION\n" "This mode is used to flash Squeezelite into the OTA partition\n" @@ -354,7 +334,7 @@ void console_start() { /* Figure out if the terminal supports escape sequences */ int probe_status = linenoiseProbe(); - if (probe_status) { /* zero indicates success */ + if(probe_status) { /* zero indicates success */ printf("\n****************************\n" "Your terminal application does not support escape sequences.\n" "Line editing and history features are disabled.\n" @@ -365,9 +345,7 @@ void console_start() { /* Since the terminal doesn't support escape sequences, * don't use color codes in the prompt. */ - if (is_recovery_running) { - recovery_prompt = "recovery-squeezelite-esp32>"; - } + if(is_recovery_running) { recovery_prompt = "recovery-squeezelite-esp32>"; } prompt = "squeezelite-esp32> "; #endif // CONFIG_LOG_COLORS } @@ -375,9 +353,7 @@ void console_start() { cfg.thread_name = "console"; cfg.inherit_cfg = true; cfg.stack_size = 4 * 1024; - if (is_recovery_running) { - prompt = recovery_prompt; - } + if(is_recovery_running) { prompt = recovery_prompt; } esp_pthread_set_cfg(&cfg); pthread_create(&thread_console, NULL, console_thread, NULL); } @@ -387,16 +363,16 @@ static esp_err_t run_command(char* line) { int ret; esp_err_t err = esp_console_run(line, &ret); - if (err == ESP_ERR_NOT_FOUND) { + if(err == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "Unrecognized command: %s", line); - } else if (err == ESP_ERR_INVALID_ARG) { + } else if(err == ESP_ERR_INVALID_ARG) { // command was empty - } else if (err != ESP_OK && ret != ESP_OK) { + } else if(err != ESP_OK && ret != ESP_OK) { ESP_LOGW(TAG, "Command returned non-zero error code: 0x%x (%s)", ret, esp_err_to_name(err)); - } else if (err == ESP_OK && ret != ESP_OK) { + } else if(err == ESP_OK && ret != ESP_OK) { ESP_LOGW(TAG, "Command returned in error"); err = ESP_FAIL; - } else if (err != ESP_OK) { + } else if(err != ESP_OK) { ESP_LOGE(TAG, "Internal error: %s", esp_err_to_name(err)); } return err; @@ -404,12 +380,12 @@ static esp_err_t run_command(char* line) { static void* console_thread() { /* Main loop */ - while (1) { + while(1) { /* Get a line using linenoise. * The line is returned when ENTER is pressed. */ char* line = linenoise(prompt); - if (line == NULL) { /* Ignore empty lines */ + if(line == NULL) { /* Ignore empty lines */ continue; } /* Add the command to the history */ diff --git a/components/platform_console/platform_console.h b/components/platform_console/platform_console.h index 71c2d2cb..f460af4c 100644 --- a/components/platform_console/platform_console.h +++ b/components/platform_console/platform_console.h @@ -13,17 +13,17 @@ #ifdef __cplusplus extern "C" { #endif -#define CFG_TYPE_HW(a) "cfg-hw-" a -#define CFG_TYPE_AUDIO(a) "cfg-audio-" a -#define CFG_TYPE_SYST(a) "cfg-syst-" a -#define CFG_TYPE_FW(a) "cfg-fw-" a -#define CFG_TYPE_GEN(a) "cfg-gen-" a -typedef cJSON * parm_values_fn_t(void); -esp_err_t cmd_to_json(const esp_console_cmd_t *cmd); -esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t *cmd, parm_values_fn_t parm_values_fn); -int arg_parse_msg(int argc, char **argv, struct arg_hdr ** args); +#define CFG_TYPE_HW(a) "cfg-hw-" a +#define CFG_TYPE_AUDIO(a) "cfg-audio-" a +#define CFG_TYPE_SYST(a) "cfg-syst-" a +#define CFG_TYPE_FW(a) "cfg-fw-" a +#define CFG_TYPE_GEN(a) "cfg-gen-" a +typedef cJSON* parm_values_fn_t(void); +esp_err_t cmd_to_json(const esp_console_cmd_t* cmd); +esp_err_t cmd_to_json_with_cb(const esp_console_cmd_t* cmd, parm_values_fn_t parm_values_fn); +int arg_parse_msg(int argc, char** argv, struct arg_hdr** args); void initialize_console(); -cJSON * get_cmd_list(); +cJSON* get_cmd_list(); #ifdef __cplusplus } #endif diff --git a/components/platform_console/test/test_system.c b/components/platform_console/test/test_system.c index 715d1c8f..c9e5de5e 100644 --- a/components/platform_console/test/test_system.c +++ b/components/platform_console/test/test_system.c @@ -14,58 +14,52 @@ // #include "Config.h" #pragma message("fixme: search for TODO below") #include "string.h" -struct arg_lit *arglit; -struct arg_int *argint; -struct arg_str *argstr; -struct arg_end *end; +struct arg_lit* arglit; +struct arg_int* argint; +struct arg_str* argstr; +struct arg_end* end; -extern int is_output_gpio(struct arg_int * gpio, FILE * f, int * gpio_out, bool mandatory); +extern int is_output_gpio(struct arg_int* gpio, FILE* f, int* gpio_out, bool mandatory); extern void initialize_console(); -extern esp_err_t run_command(char * line); -static char *buf = NULL; -static char * s_tmp_line_buf=NULL; +extern esp_err_t run_command(char* line); +static char* buf = NULL; +static char* s_tmp_line_buf = NULL; static size_t buf_size = 0; -static FILE * f; -static size_t argc=1; -static char ** argv=NULL; -static bool config_initialized=false; -void init_console(){ +static FILE* f; +static size_t argc = 1; +static char** argv = NULL; +static bool config_initialized = false; +void init_console() { if(config_initialized) return; initialize_console(); - config_initialized=true; + config_initialized = true; } /**************************************************************************************** * */ -void open_mem_stream_file(){ - f = open_memstream(&buf, &buf_size); -} +void open_mem_stream_file() { f = open_memstream(&buf, &buf_size); } /**************************************************************************************** * */ -void close_flush_all(void * argtable, int count,bool print){ - fflush (f); - if(print){ - printf("%s", buf); - } +void close_flush_all(void* argtable, int count, bool print) { + fflush(f); + if(print) { printf("%s", buf); } fclose(f); free(buf); - arg_freetable(argtable,count); - free(argv); + arg_freetable(argtable, count); + free(argv); } /**************************************************************************************** * */ -int alloc_split_command_line(char * cmdline){ - argv = (char **) calloc(22, sizeof(char *)); - if(!s_tmp_line_buf){ - s_tmp_line_buf= calloc(strlen(cmdline), 1); - } +int alloc_split_command_line(char* cmdline) { + argv = (char**)calloc(22, sizeof(char*)); + if(!s_tmp_line_buf) { s_tmp_line_buf = calloc(strlen(cmdline), 1); } strlcpy(s_tmp_line_buf, cmdline, 22); - argc = esp_console_split_argv(s_tmp_line_buf, argv,22); + argc = esp_console_split_argv(s_tmp_line_buf, argv, 22); return 0; } @@ -73,118 +67,97 @@ int alloc_split_command_line(char * cmdline){ /**************************************************************************************** * */ -int alloc_split_parse_command_line(char * cmdline, void ** args){ +int alloc_split_parse_command_line(char* cmdline, void** args) { alloc_split_command_line(cmdline); - return arg_parse(argc, argv,args); + return arg_parse(argc, argv, args); } /**************************************************************************************** * */ -TEST_CASE("Invalid GPIO detected", "[config][ui]") -{ - char * cmdline = "test -i 55\n"; - void *argtable[] = { - argint = arg_int1("i","int","","GPIO number"), - end = arg_end(6) - }; +TEST_CASE("Invalid GPIO detected", "[config][ui]") { + char* cmdline = "test -i 55\n"; + void* argtable[] = {argint = arg_int1("i", "int", "", "GPIO number"), end = arg_end(6)}; open_mem_stream_file(); alloc_split_parse_command_line(cmdline, &argtable); int out_val = 0; - TEST_ASSERT_EQUAL_INT_MESSAGE(1,is_output_gpio(argtable[0], f, &out_val, true),"Invalid GPIO not detected"); - TEST_ASSERT_EQUAL_INT_MESSAGE(-1,out_val,"GPIO Should be set to -1"); - fflush (f); - TEST_ASSERT_EQUAL_STRING_MESSAGE("Invalid int gpio: [55] is not a GPIO\n",buf,"Invalid GPIO message wrong"); - close_flush_all(argtable,sizeof(argtable)/sizeof(argtable[0]),false); + TEST_ASSERT_EQUAL_INT_MESSAGE(1, is_output_gpio(argtable[0], f, &out_val, true), "Invalid GPIO not detected"); + TEST_ASSERT_EQUAL_INT_MESSAGE(-1, out_val, "GPIO Should be set to -1"); + fflush(f); + TEST_ASSERT_EQUAL_STRING_MESSAGE("Invalid int gpio: [55] is not a GPIO\n", buf, "Invalid GPIO message wrong"); + close_flush_all(argtable, sizeof(argtable) / sizeof(argtable[0]), false); } /**************************************************************************************** * */ -TEST_CASE("Input Only GPIO detected", "[config][ui]") -{ - char * cmdline = "test -i 35\n"; - void *argtable[] = { - argint = arg_int1("i","int","","GPIO number"), - end = arg_end(6) - }; +TEST_CASE("Input Only GPIO detected", "[config][ui]") { + char* cmdline = "test -i 35\n"; + void* argtable[] = {argint = arg_int1("i", "int", "", "GPIO number"), end = arg_end(6)}; open_mem_stream_file(); alloc_split_parse_command_line(cmdline, &argtable); int out_val = 0; - TEST_ASSERT_EQUAL_INT_MESSAGE(1,is_output_gpio(argtable[0], f, &out_val, true),"Input only GPIO not detected"); - TEST_ASSERT_EQUAL_INT_MESSAGE(-1,out_val,"GPIO Should be set to -1"); - fflush (f); - TEST_ASSERT_EQUAL_STRING_MESSAGE("Invalid int gpio: [35] has input capabilities only\n",buf,"Missing GPIO message wrong"); - close_flush_all(argtable,sizeof(argtable)/sizeof(argtable[0]),false); + TEST_ASSERT_EQUAL_INT_MESSAGE(1, is_output_gpio(argtable[0], f, &out_val, true), "Input only GPIO not detected"); + TEST_ASSERT_EQUAL_INT_MESSAGE(-1, out_val, "GPIO Should be set to -1"); + fflush(f); + TEST_ASSERT_EQUAL_STRING_MESSAGE("Invalid int gpio: [35] has input capabilities only\n", buf, "Missing GPIO message wrong"); + close_flush_all(argtable, sizeof(argtable) / sizeof(argtable[0]), false); } /**************************************************************************************** * */ -TEST_CASE("Valid GPIO Processed", "[config][ui]") -{ - char * cmdline = "test -i 33\n"; - void *argtable[] = { - argint = arg_int1("i","int","","GPIO number"), - end = arg_end(6) - }; +TEST_CASE("Valid GPIO Processed", "[config][ui]") { + char* cmdline = "test -i 33\n"; + void* argtable[] = {argint = arg_int1("i", "int", "", "GPIO number"), end = arg_end(6)}; open_mem_stream_file(); alloc_split_parse_command_line(cmdline, &argtable); int out_val = 0; - TEST_ASSERT_EQUAL_INT_MESSAGE(0,is_output_gpio(argtable[0], f, &out_val, true),"Valid GPIO not recognized"); - TEST_ASSERT_EQUAL_INT_MESSAGE(33,out_val,"GPIO Should be set to 33"); - fflush (f); - TEST_ASSERT_EQUAL_STRING_MESSAGE("",buf,"Valid GPIO shouldn't produce a message"); - close_flush_all(argtable,sizeof(argtable)/sizeof(argtable[0]),false); + TEST_ASSERT_EQUAL_INT_MESSAGE(0, is_output_gpio(argtable[0], f, &out_val, true), "Valid GPIO not recognized"); + TEST_ASSERT_EQUAL_INT_MESSAGE(33, out_val, "GPIO Should be set to 33"); + fflush(f); + TEST_ASSERT_EQUAL_STRING_MESSAGE("", buf, "Valid GPIO shouldn't produce a message"); + close_flush_all(argtable, sizeof(argtable) / sizeof(argtable[0]), false); } /**************************************************************************************** * */ -TEST_CASE("Missing mandatory GPIO detected", "[config][ui]") -{ - char * cmdline = "test \n"; - void *argtable[] = { - argint = arg_int1("i","int","","GPIO number"), - end = arg_end(6) - }; +TEST_CASE("Missing mandatory GPIO detected", "[config][ui]") { + char* cmdline = "test \n"; + void* argtable[] = {argint = arg_int1("i", "int", "", "GPIO number"), end = arg_end(6)}; open_mem_stream_file(); alloc_split_parse_command_line(cmdline, &argtable); int out_val = 0; - TEST_ASSERT_EQUAL_INT_MESSAGE(1,is_output_gpio(argtable[0], f, &out_val, true),"Missing GPIO not detected"); - fflush (f); - TEST_ASSERT_EQUAL_STRING_MESSAGE("Missing: int\n",buf,"Missing GPIO parameter message wrong"); - TEST_ASSERT_EQUAL_INT_MESSAGE(-1,out_val,"GPIO Should be set to -1"); - close_flush_all(argtable,sizeof(argtable)/sizeof(argtable[0]),false); + TEST_ASSERT_EQUAL_INT_MESSAGE(1, is_output_gpio(argtable[0], f, &out_val, true), "Missing GPIO not detected"); + fflush(f); + TEST_ASSERT_EQUAL_STRING_MESSAGE("Missing: int\n", buf, "Missing GPIO parameter message wrong"); + TEST_ASSERT_EQUAL_INT_MESSAGE(-1, out_val, "GPIO Should be set to -1"); + close_flush_all(argtable, sizeof(argtable) / sizeof(argtable[0]), false); } /**************************************************************************************** * */ -TEST_CASE("Missing mandatory parameter detected", "[config][ui]") -{ - char * cmdline = "test \n"; - void *argtable[] = { - argint = arg_int1("i","int","","GPIO number"), - end = arg_end(6) - }; +TEST_CASE("Missing mandatory parameter detected", "[config][ui]") { + char* cmdline = "test \n"; + void* argtable[] = {argint = arg_int1("i", "int", "", "GPIO number"), end = arg_end(6)}; open_mem_stream_file(); alloc_split_parse_command_line(cmdline, &argtable); int out_val = 0; - TEST_ASSERT_EQUAL_INT_MESSAGE(1,is_output_gpio(argtable[0], f, &out_val, true),"Missing parameter not detected"); - fflush (f); - TEST_ASSERT_EQUAL_STRING_MESSAGE("Missing: int\n",buf,"Missing parameter message wrong"); - TEST_ASSERT_EQUAL_INT_MESSAGE(-1,out_val,"GPIO Should be set to -1"); - close_flush_all(argtable,sizeof(argtable)/sizeof(argtable[0]),false); + TEST_ASSERT_EQUAL_INT_MESSAGE(1, is_output_gpio(argtable[0], f, &out_val, true), "Missing parameter not detected"); + fflush(f); + TEST_ASSERT_EQUAL_STRING_MESSAGE("Missing: int\n", buf, "Missing parameter message wrong"); + TEST_ASSERT_EQUAL_INT_MESSAGE(-1, out_val, "GPIO Should be set to -1"); + close_flush_all(argtable, sizeof(argtable) / sizeof(argtable[0]), false); } /**************************************************************************************** * */ -TEST_CASE("dac config command", "[config_cmd]") -{ +TEST_CASE("dac config command", "[config_cmd]") { config_set_value(NVS_TYPE_STR, "dac_config", ""); - esp_err_t err=run_command("cfg-hw-dac\n"); - char * nvs_value = config_alloc_get_str("dac_config", NULL,NULL); + esp_err_t err = run_command("cfg-hw-dac\n"); + char* nvs_value = config_alloc_get_str("dac_config", NULL, NULL); TEST_ASSERT_NOT_NULL(nvs_value); - TEST_ASSERT_EQUAL_MESSAGE(ESP_OK,err,"Running command failed"); + TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, err, "Running command failed"); free(nvs_value); } diff --git a/components/raop/dmap_parser.c b/components/raop/dmap_parser.c index b013ad1d..757766a8 100644 --- a/components/raop/dmap_parser.c +++ b/components/raop/dmap_parser.c @@ -7,546 +7,330 @@ #define DMAP_STRINGIFY_(x) #x #define DMAP_STRINGIFY(x) DMAP_STRINGIFY_(x) -typedef enum { - DMAP_UNKNOWN, - DMAP_UINT, - DMAP_INT, - DMAP_STR, - DMAP_DATA, - DMAP_DATE, - DMAP_VERS, - DMAP_DICT, - DMAP_ITEM -} DMAP_TYPE; +typedef enum { DMAP_UNKNOWN, DMAP_UINT, DMAP_INT, DMAP_STR, DMAP_DATA, DMAP_DATE, DMAP_VERS, DMAP_DICT, DMAP_ITEM } DMAP_TYPE; typedef struct { - /** + /** * The four-character code used in the encoded message. */ - const char *code; + const char* code; - /** + /** * The type of data associated with the content code. */ - DMAP_TYPE type; + DMAP_TYPE type; - /** + /** * For listings, the type of their listing item children. * * Listing items (mlit) can be of any type, and as with other content codes * their type information is not encoded in the message. Parsers must * determine the type of the listing items based on their parent context. */ - DMAP_TYPE list_item_type; + DMAP_TYPE list_item_type; - /** + /** * A human-readable name for the content code. */ - const char *name; + const char* name; } dmap_field; static const dmap_field dmap_fields[] = { #ifdef DMAP_FULL - { "abal", DMAP_DICT, DMAP_STR, "daap.browsealbumlisting" }, - { "abar", DMAP_DICT, DMAP_STR, "daap.browseartistlisting" }, - { "abcp", DMAP_DICT, DMAP_STR, "daap.browsecomposerlisting" }, - { "abgn", DMAP_DICT, DMAP_STR, "daap.browsegenrelisting" }, - { "abpl", DMAP_UINT, 0, "daap.baseplaylist" }, - { "abro", DMAP_DICT, 0, "daap.databasebrowse" }, - { "adbs", DMAP_DICT, 0, "daap.databasesongs" }, - { "aeAD", DMAP_DICT, 0, "com.apple.itunes.adam-ids-array" }, - { "aeAI", DMAP_UINT, 0, "com.apple.itunes.itms-artistid" }, - { "aeCD", DMAP_DATA, 0, "com.apple.itunes.flat-chapter-data" }, - { "aeCF", DMAP_UINT, 0, "com.apple.itunes.cloud-flavor-id" }, - { "aeCI", DMAP_UINT, 0, "com.apple.itunes.itms-composerid" }, - { "aeCK", DMAP_UINT, 0, "com.apple.itunes.cloud-library-kind" }, - { "aeCM", DMAP_UINT, 0, "com.apple.itunes.cloud-match-type" }, - { "aeCR", DMAP_STR, 0, "com.apple.itunes.content-rating" } , - { "aeCS", DMAP_UINT, 0, "com.apple.itunes.artworkchecksum" }, - { "aeCU", DMAP_UINT, 0, "com.apple.itunes.cloud-user-id" }, - { "aeCd", DMAP_UINT, 0, "com.apple.itunes.cloud-id" }, - { "aeDE", DMAP_STR, 0, "com.apple.itunes.longest-content-description" }, - { "aeDL", DMAP_UINT, 0, "com.apple.itunes.drm-downloader-user-id" }, - { "aeDP", DMAP_UINT, 0, "com.apple.itunes.drm-platform-id" }, - { "aeDR", DMAP_UINT, 0, "com.apple.itunes.drm-user-id" }, - { "aeDV", DMAP_UINT, 0, "com.apple.itunes.drm-versions" }, - { "aeEN", DMAP_STR, 0, "com.apple.itunes.episode-num-str" }, - { "aeES", DMAP_UINT, 0, "com.apple.itunes.episode-sort" }, - { "aeFA", DMAP_UINT, 0, "com.apple.itunes.drm-family-id" }, - { "aeGD", DMAP_UINT, 0, "com.apple.itunes.gapless-enc-dr" } , - { "aeGE", DMAP_UINT, 0, "com.apple.itunes.gapless-enc-del" }, - { "aeGH", DMAP_UINT, 0, "com.apple.itunes.gapless-heur" }, - { "aeGI", DMAP_UINT, 0, "com.apple.itunes.itms-genreid" }, - { "aeGR", DMAP_UINT, 0, "com.apple.itunes.gapless-resy" }, - { "aeGU", DMAP_UINT, 0, "com.apple.itunes.gapless-dur" }, - { "aeGs", DMAP_UINT, 0, "com.apple.itunes.can-be-genius-seed" }, - { "aeHC", DMAP_UINT, 0, "com.apple.itunes.has-chapter-data" }, - { "aeHD", DMAP_UINT, 0, "com.apple.itunes.is-hd-video" }, - { "aeHV", DMAP_UINT, 0, "com.apple.itunes.has-video" }, - { "aeK1", DMAP_UINT, 0, "com.apple.itunes.drm-key1-id" }, - { "aeK2", DMAP_UINT, 0, "com.apple.itunes.drm-key2-id" }, - { "aeMC", DMAP_UINT, 0, "com.apple.itunes.playlist-contains-media-type-count" }, - { "aeMK", DMAP_UINT, 0, "com.apple.itunes.mediakind" }, - { "aeMX", DMAP_STR, 0, "com.apple.itunes.movie-info-xml" }, - { "aeMk", DMAP_UINT, 0, "com.apple.itunes.extended-media-kind" }, - { "aeND", DMAP_UINT, 0, "com.apple.itunes.non-drm-user-id" }, - { "aeNN", DMAP_STR, 0, "com.apple.itunes.network-name" }, - { "aeNV", DMAP_UINT, 0, "com.apple.itunes.norm-volume" }, - { "aePC", DMAP_UINT, 0, "com.apple.itunes.is-podcast" }, - { "aePI", DMAP_UINT, 0, "com.apple.itunes.itms-playlistid" }, - { "aePP", DMAP_UINT, 0, "com.apple.itunes.is-podcast-playlist" }, - { "aePS", DMAP_UINT, 0, "com.apple.itunes.special-playlist" }, - { "aeRD", DMAP_UINT, 0, "com.apple.itunes.rental-duration" }, - { "aeRP", DMAP_UINT, 0, "com.apple.itunes.rental-pb-start" }, - { "aeRS", DMAP_UINT, 0, "com.apple.itunes.rental-start" }, - { "aeRU", DMAP_UINT, 0, "com.apple.itunes.rental-pb-duration" }, - { "aeRf", DMAP_UINT, 0, "com.apple.itunes.is-featured" }, - { "aeSE", DMAP_UINT, 0, "com.apple.itunes.store-pers-id" }, - { "aeSF", DMAP_UINT, 0, "com.apple.itunes.itms-storefrontid" }, - { "aeSG", DMAP_UINT, 0, "com.apple.itunes.saved-genius" }, - { "aeSI", DMAP_UINT, 0, "com.apple.itunes.itms-songid" }, - { "aeSN", DMAP_STR, 0, "com.apple.itunes.series-name" }, - { "aeSP", DMAP_UINT, 0, "com.apple.itunes.smart-playlist" }, - { "aeSU", DMAP_UINT, 0, "com.apple.itunes.season-num" }, - { "aeSV", DMAP_VERS, 0, "com.apple.itunes.music-sharing-version" }, - { "aeXD", DMAP_STR, 0, "com.apple.itunes.xid" }, - { "aecp", DMAP_STR, 0, "com.apple.itunes.collection-description" }, - { "aels", DMAP_UINT, 0, "com.apple.itunes.liked-state" }, - { "aemi", DMAP_DICT, 0, "com.apple.itunes.media-kind-listing-item" }, - { "aeml", DMAP_DICT, 0, "com.apple.itunes.media-kind-listing" }, - { "agac", DMAP_UINT, 0, "daap.groupalbumcount" }, - { "agma", DMAP_UINT, 0, "daap.groupmatchedqueryalbumcount" }, - { "agmi", DMAP_UINT, 0, "daap.groupmatchedqueryitemcount" }, - { "agrp", DMAP_STR, 0, "daap.songgrouping" }, - { "ajAE", DMAP_UINT, 0, "com.apple.itunes.store.ams-episode-type" }, - { "ajAS", DMAP_UINT, 0, "com.apple.itunes.store.ams-episode-sort-order" }, - { "ajAT", DMAP_UINT, 0, "com.apple.itunes.store.ams-show-type" }, - { "ajAV", DMAP_UINT, 0, "com.apple.itunes.store.is-ams-video" }, - { "ajal", DMAP_UINT, 0, "com.apple.itunes.store.album-liked-state" }, - { "ajcA", DMAP_UINT, 0, "com.apple.itunes.store.show-composer-as-artist" }, - { "ajca", DMAP_UINT, 0, "com.apple.itunes.store.show-composer-as-artist" }, - { "ajuw", DMAP_UINT, 0, "com.apple.itunes.store.use-work-name-as-display-name" }, - { "amvc", DMAP_UINT, 0, "daap.songmovementcount" }, - { "amvm", DMAP_STR, 0, "daap.songmovementname" }, - { "amvn", DMAP_UINT, 0, "daap.songmovementnumber" }, - { "aply", DMAP_DICT, 0, "daap.databaseplaylists" }, - { "aprm", DMAP_UINT, 0, "daap.playlistrepeatmode" }, - { "apro", DMAP_VERS, 0, "daap.protocolversion" }, - { "apsm", DMAP_UINT, 0, "daap.playlistshufflemode" }, - { "apso", DMAP_DICT, 0, "daap.playlistsongs" }, - { "arif", DMAP_DICT, 0, "daap.resolveinfo" }, - { "arsv", DMAP_DICT, 0, "daap.resolve" }, - { "asaa", DMAP_STR, 0, "daap.songalbumartist" }, - { "asac", DMAP_UINT, 0, "daap.songartworkcount" }, - { "asai", DMAP_UINT, 0, "daap.songalbumid" }, + {"abal", DMAP_DICT, DMAP_STR, "daap.browsealbumlisting"}, {"abar", DMAP_DICT, DMAP_STR, "daap.browseartistlisting"}, + {"abcp", DMAP_DICT, DMAP_STR, "daap.browsecomposerlisting"}, {"abgn", DMAP_DICT, DMAP_STR, "daap.browsegenrelisting"}, + {"abpl", DMAP_UINT, 0, "daap.baseplaylist"}, {"abro", DMAP_DICT, 0, "daap.databasebrowse"}, {"adbs", DMAP_DICT, 0, "daap.databasesongs"}, + {"aeAD", DMAP_DICT, 0, "com.apple.itunes.adam-ids-array"}, {"aeAI", DMAP_UINT, 0, "com.apple.itunes.itms-artistid"}, + {"aeCD", DMAP_DATA, 0, "com.apple.itunes.flat-chapter-data"}, {"aeCF", DMAP_UINT, 0, "com.apple.itunes.cloud-flavor-id"}, + {"aeCI", DMAP_UINT, 0, "com.apple.itunes.itms-composerid"}, {"aeCK", DMAP_UINT, 0, "com.apple.itunes.cloud-library-kind"}, + {"aeCM", DMAP_UINT, 0, "com.apple.itunes.cloud-match-type"}, {"aeCR", DMAP_STR, 0, "com.apple.itunes.content-rating"}, + {"aeCS", DMAP_UINT, 0, "com.apple.itunes.artworkchecksum"}, {"aeCU", DMAP_UINT, 0, "com.apple.itunes.cloud-user-id"}, + {"aeCd", DMAP_UINT, 0, "com.apple.itunes.cloud-id"}, {"aeDE", DMAP_STR, 0, "com.apple.itunes.longest-content-description"}, + {"aeDL", DMAP_UINT, 0, "com.apple.itunes.drm-downloader-user-id"}, {"aeDP", DMAP_UINT, 0, "com.apple.itunes.drm-platform-id"}, + {"aeDR", DMAP_UINT, 0, "com.apple.itunes.drm-user-id"}, {"aeDV", DMAP_UINT, 0, "com.apple.itunes.drm-versions"}, + {"aeEN", DMAP_STR, 0, "com.apple.itunes.episode-num-str"}, {"aeES", DMAP_UINT, 0, "com.apple.itunes.episode-sort"}, + {"aeFA", DMAP_UINT, 0, "com.apple.itunes.drm-family-id"}, {"aeGD", DMAP_UINT, 0, "com.apple.itunes.gapless-enc-dr"}, + {"aeGE", DMAP_UINT, 0, "com.apple.itunes.gapless-enc-del"}, {"aeGH", DMAP_UINT, 0, "com.apple.itunes.gapless-heur"}, + {"aeGI", DMAP_UINT, 0, "com.apple.itunes.itms-genreid"}, {"aeGR", DMAP_UINT, 0, "com.apple.itunes.gapless-resy"}, + {"aeGU", DMAP_UINT, 0, "com.apple.itunes.gapless-dur"}, {"aeGs", DMAP_UINT, 0, "com.apple.itunes.can-be-genius-seed"}, + {"aeHC", DMAP_UINT, 0, "com.apple.itunes.has-chapter-data"}, {"aeHD", DMAP_UINT, 0, "com.apple.itunes.is-hd-video"}, + {"aeHV", DMAP_UINT, 0, "com.apple.itunes.has-video"}, {"aeK1", DMAP_UINT, 0, "com.apple.itunes.drm-key1-id"}, + {"aeK2", DMAP_UINT, 0, "com.apple.itunes.drm-key2-id"}, {"aeMC", DMAP_UINT, 0, "com.apple.itunes.playlist-contains-media-type-count"}, + {"aeMK", DMAP_UINT, 0, "com.apple.itunes.mediakind"}, {"aeMX", DMAP_STR, 0, "com.apple.itunes.movie-info-xml"}, + {"aeMk", DMAP_UINT, 0, "com.apple.itunes.extended-media-kind"}, {"aeND", DMAP_UINT, 0, "com.apple.itunes.non-drm-user-id"}, + {"aeNN", DMAP_STR, 0, "com.apple.itunes.network-name"}, {"aeNV", DMAP_UINT, 0, "com.apple.itunes.norm-volume"}, + {"aePC", DMAP_UINT, 0, "com.apple.itunes.is-podcast"}, {"aePI", DMAP_UINT, 0, "com.apple.itunes.itms-playlistid"}, + {"aePP", DMAP_UINT, 0, "com.apple.itunes.is-podcast-playlist"}, {"aePS", DMAP_UINT, 0, "com.apple.itunes.special-playlist"}, + {"aeRD", DMAP_UINT, 0, "com.apple.itunes.rental-duration"}, {"aeRP", DMAP_UINT, 0, "com.apple.itunes.rental-pb-start"}, + {"aeRS", DMAP_UINT, 0, "com.apple.itunes.rental-start"}, {"aeRU", DMAP_UINT, 0, "com.apple.itunes.rental-pb-duration"}, + {"aeRf", DMAP_UINT, 0, "com.apple.itunes.is-featured"}, {"aeSE", DMAP_UINT, 0, "com.apple.itunes.store-pers-id"}, + {"aeSF", DMAP_UINT, 0, "com.apple.itunes.itms-storefrontid"}, {"aeSG", DMAP_UINT, 0, "com.apple.itunes.saved-genius"}, + {"aeSI", DMAP_UINT, 0, "com.apple.itunes.itms-songid"}, {"aeSN", DMAP_STR, 0, "com.apple.itunes.series-name"}, + {"aeSP", DMAP_UINT, 0, "com.apple.itunes.smart-playlist"}, {"aeSU", DMAP_UINT, 0, "com.apple.itunes.season-num"}, + {"aeSV", DMAP_VERS, 0, "com.apple.itunes.music-sharing-version"}, {"aeXD", DMAP_STR, 0, "com.apple.itunes.xid"}, + {"aecp", DMAP_STR, 0, "com.apple.itunes.collection-description"}, {"aels", DMAP_UINT, 0, "com.apple.itunes.liked-state"}, + {"aemi", DMAP_DICT, 0, "com.apple.itunes.media-kind-listing-item"}, {"aeml", DMAP_DICT, 0, "com.apple.itunes.media-kind-listing"}, + {"agac", DMAP_UINT, 0, "daap.groupalbumcount"}, {"agma", DMAP_UINT, 0, "daap.groupmatchedqueryalbumcount"}, + {"agmi", DMAP_UINT, 0, "daap.groupmatchedqueryitemcount"}, {"agrp", DMAP_STR, 0, "daap.songgrouping"}, + {"ajAE", DMAP_UINT, 0, "com.apple.itunes.store.ams-episode-type"}, {"ajAS", DMAP_UINT, 0, "com.apple.itunes.store.ams-episode-sort-order"}, + {"ajAT", DMAP_UINT, 0, "com.apple.itunes.store.ams-show-type"}, {"ajAV", DMAP_UINT, 0, "com.apple.itunes.store.is-ams-video"}, + {"ajal", DMAP_UINT, 0, "com.apple.itunes.store.album-liked-state"}, {"ajcA", DMAP_UINT, 0, "com.apple.itunes.store.show-composer-as-artist"}, + {"ajca", DMAP_UINT, 0, "com.apple.itunes.store.show-composer-as-artist"}, + {"ajuw", DMAP_UINT, 0, "com.apple.itunes.store.use-work-name-as-display-name"}, {"amvc", DMAP_UINT, 0, "daap.songmovementcount"}, + {"amvm", DMAP_STR, 0, "daap.songmovementname"}, {"amvn", DMAP_UINT, 0, "daap.songmovementnumber"}, + {"aply", DMAP_DICT, 0, "daap.databaseplaylists"}, {"aprm", DMAP_UINT, 0, "daap.playlistrepeatmode"}, + {"apro", DMAP_VERS, 0, "daap.protocolversion"}, {"apsm", DMAP_UINT, 0, "daap.playlistshufflemode"}, {"apso", DMAP_DICT, 0, "daap.playlistsongs"}, + {"arif", DMAP_DICT, 0, "daap.resolveinfo"}, {"arsv", DMAP_DICT, 0, "daap.resolve"}, {"asaa", DMAP_STR, 0, "daap.songalbumartist"}, + {"asac", DMAP_UINT, 0, "daap.songartworkcount"}, {"asai", DMAP_UINT, 0, "daap.songalbumid"}, #endif - { "asal", DMAP_STR, 0, "daap.songalbum" }, - { "asar", DMAP_STR, 0, "daap.songartist" }, + {"asal", DMAP_STR, 0, "daap.songalbum"}, {"asar", DMAP_STR, 0, "daap.songartist"}, #ifdef DMAP_FULL - { "asas", DMAP_UINT, 0, "daap.songalbumuserratingstatus" }, - { "asbk", DMAP_UINT, 0, "daap.bookmarkable" }, - { "asbo", DMAP_UINT, 0, "daap.songbookmark" }, - { "asbr", DMAP_UINT, 0, "daap.songbitrate" }, - { "asbt", DMAP_UINT, 0, "daap.songbeatsperminute" }, - { "ascd", DMAP_UINT, 0, "daap.songcodectype" }, - { "ascm", DMAP_STR, 0, "daap.songcomment" }, - { "ascn", DMAP_STR, 0, "daap.songcontentdescription" }, - { "asco", DMAP_UINT, 0, "daap.songcompilation" }, - { "ascp", DMAP_STR, 0, "daap.songcomposer" }, - { "ascr", DMAP_UINT, 0, "daap.songcontentrating" }, - { "ascs", DMAP_UINT, 0, "daap.songcodecsubtype" }, - { "asct", DMAP_STR, 0, "daap.songcategory" }, - { "asda", DMAP_DATE, 0, "daap.songdateadded" }, - { "asdb", DMAP_UINT, 0, "daap.songdisabled" }, - { "asdc", DMAP_UINT, 0, "daap.songdisccount" }, - { "asdk", DMAP_UINT, 0, "daap.songdatakind" }, - { "asdm", DMAP_DATE, 0, "daap.songdatemodified" }, - { "asdn", DMAP_UINT, 0, "daap.songdiscnumber" }, - { "asdp", DMAP_DATE, 0, "daap.songdatepurchased" }, - { "asdr", DMAP_DATE, 0, "daap.songdatereleased" }, - { "asdt", DMAP_STR, 0, "daap.songdescription" }, - { "ased", DMAP_UINT, 0, "daap.songextradata" }, - { "aseq", DMAP_STR, 0, "daap.songeqpreset" }, - { "ases", DMAP_UINT, 0, "daap.songexcludefromshuffle" }, - { "asfm", DMAP_STR, 0, "daap.songformat" }, - { "asgn", DMAP_STR, 0, "daap.songgenre" }, - { "asgp", DMAP_UINT, 0, "daap.songgapless" }, - { "asgr", DMAP_UINT, 0, "daap.supportsgroups" }, - { "ashp", DMAP_UINT, 0, "daap.songhasbeenplayed" }, - { "askd", DMAP_DATE, 0, "daap.songlastskipdate" }, - { "askp", DMAP_UINT, 0, "daap.songuserskipcount" }, - { "asky", DMAP_STR, 0, "daap.songkeywords" }, - { "aslc", DMAP_STR, 0, "daap.songlongcontentdescription" }, - { "aslr", DMAP_UINT, 0, "daap.songalbumuserrating" }, - { "asls", DMAP_UINT, 0, "daap.songlongsize" }, - { "aspc", DMAP_UINT, 0, "daap.songuserplaycount" }, - { "aspl", DMAP_DATE, 0, "daap.songdateplayed" }, - { "aspu", DMAP_STR, 0, "daap.songpodcasturl" }, - { "asri", DMAP_UINT, 0, "daap.songartistid" }, - { "asrs", DMAP_UINT, 0, "daap.songuserratingstatus" }, - { "asrv", DMAP_INT, 0, "daap.songrelativevolume" }, - { "assa", DMAP_STR, 0, "daap.sortartist" }, - { "assc", DMAP_STR, 0, "daap.sortcomposer" }, - { "assl", DMAP_STR, 0, "daap.sortalbumartist" }, - { "assn", DMAP_STR, 0, "daap.sortname" }, - { "assp", DMAP_UINT, 0, "daap.songstoptime" }, - { "assr", DMAP_UINT, 0, "daap.songsamplerate" }, - { "asss", DMAP_STR, 0, "daap.sortseriesname" }, - { "asst", DMAP_UINT, 0, "daap.songstarttime" }, - { "assu", DMAP_STR, 0, "daap.sortalbum" }, - { "assz", DMAP_UINT, 0, "daap.songsize" }, - { "astc", DMAP_UINT, 0, "daap.songtrackcount" }, - { "astm", DMAP_UINT, 0, "daap.songtime" }, - { "astn", DMAP_UINT, 0, "daap.songtracknumber" }, - { "asul", DMAP_STR, 0, "daap.songdataurl" }, - { "asur", DMAP_UINT, 0, "daap.songuserrating" }, - { "asvc", DMAP_UINT, 0, "daap.songprimaryvideocodec" }, - { "asyr", DMAP_UINT, 0, "daap.songyear" }, - { "ated", DMAP_UINT, 0, "daap.supportsextradata" }, - { "avdb", DMAP_DICT, 0, "daap.serverdatabases" }, - { "awrk", DMAP_STR, 0, "daap.songwork" }, - { "caar", DMAP_UINT, 0, "dacp.availablerepeatstates" }, - { "caas", DMAP_UINT, 0, "dacp.availableshufflestates" }, - { "caci", DMAP_DICT, 0, "caci" }, - { "cafe", DMAP_UINT, 0, "dacp.fullscreenenabled" }, - { "cafs", DMAP_UINT, 0, "dacp.fullscreen" }, - { "caia", DMAP_UINT, 0, "dacp.isactive" }, - { "cana", DMAP_STR, 0, "dacp.nowplayingartist" }, - { "cang", DMAP_STR, 0, "dacp.nowplayinggenre" }, - { "canl", DMAP_STR, 0, "dacp.nowplayingalbum" }, - { "cann", DMAP_STR, 0, "dacp.nowplayingname" }, - { "canp", DMAP_UINT, 0, "dacp.nowplayingids" }, - { "cant", DMAP_UINT, 0, "dacp.nowplayingtime" }, - { "capr", DMAP_VERS, 0, "dacp.protocolversion" }, - { "caps", DMAP_UINT, 0, "dacp.playerstate" }, - { "carp", DMAP_UINT, 0, "dacp.repeatstate" }, - { "cash", DMAP_UINT, 0, "dacp.shufflestate" }, - { "casp", DMAP_DICT, 0, "dacp.speakers" }, - { "cast", DMAP_UINT, 0, "dacp.songtime" }, - { "cavc", DMAP_UINT, 0, "dacp.volumecontrollable" }, - { "cave", DMAP_UINT, 0, "dacp.visualizerenabled" }, - { "cavs", DMAP_UINT, 0, "dacp.visualizer" }, - { "ceJC", DMAP_UINT, 0, "com.apple.itunes.jukebox-client-vote" }, - { "ceJI", DMAP_UINT, 0, "com.apple.itunes.jukebox-current" }, - { "ceJS", DMAP_UINT, 0, "com.apple.itunes.jukebox-score" }, - { "ceJV", DMAP_UINT, 0, "com.apple.itunes.jukebox-vote" }, - { "ceQR", DMAP_DICT, 0, "com.apple.itunes.playqueue-contents-response" }, - { "ceQa", DMAP_STR, 0, "com.apple.itunes.playqueue-album" }, - { "ceQg", DMAP_STR, 0, "com.apple.itunes.playqueue-genre" }, - { "ceQn", DMAP_STR, 0, "com.apple.itunes.playqueue-name" }, - { "ceQr", DMAP_STR, 0, "com.apple.itunes.playqueue-artist" }, - { "cmgt", DMAP_DICT, 0, "dmcp.getpropertyresponse" }, - { "cmmk", DMAP_UINT, 0, "dmcp.mediakind" }, - { "cmpr", DMAP_VERS, 0, "dmcp.protocolversion" }, - { "cmsr", DMAP_UINT, 0, "dmcp.serverrevision" }, - { "cmst", DMAP_DICT, 0, "dmcp.playstatus" }, - { "cmvo", DMAP_UINT, 0, "dmcp.volume" }, - { "f\215ch", DMAP_UINT, 0, "dmap.haschildcontainers" }, - { "ipsa", DMAP_DICT, 0, "dpap.iphotoslideshowadvancedoptions" }, - { "ipsl", DMAP_DICT, 0, "dpap.iphotoslideshowoptions" }, - { "mbcl", DMAP_DICT, 0, "dmap.bag" }, - { "mccr", DMAP_DICT, 0, "dmap.contentcodesresponse" }, - { "mcna", DMAP_STR, 0, "dmap.contentcodesname" }, - { "mcnm", DMAP_UINT, 0, "dmap.contentcodesnumber" }, - { "mcon", DMAP_DICT, 0, "dmap.container" }, - { "mctc", DMAP_UINT, 0, "dmap.containercount" }, - { "mcti", DMAP_UINT, 0, "dmap.containeritemid" }, - { "mcty", DMAP_UINT, 0, "dmap.contentcodestype" }, - { "mdbk", DMAP_UINT, 0, "dmap.databasekind" }, - { "mdcl", DMAP_DICT, 0, "dmap.dictionary" }, - { "mdst", DMAP_UINT, 0, "dmap.downloadstatus" }, - { "meds", DMAP_UINT, 0, "dmap.editcommandssupported" }, - { "meia", DMAP_UINT, 0, "dmap.itemdateadded" }, - { "meip", DMAP_UINT, 0, "dmap.itemdateplayed" }, - { "mext", DMAP_UINT, 0, "dmap.objectextradata" }, - { "miid", DMAP_UINT, 0, "dmap.itemid" }, - { "mikd", DMAP_UINT, 0, "dmap.itemkind" }, - { "mimc", DMAP_UINT, 0, "dmap.itemcount" }, + {"asas", DMAP_UINT, 0, "daap.songalbumuserratingstatus"}, {"asbk", DMAP_UINT, 0, "daap.bookmarkable"}, + {"asbo", DMAP_UINT, 0, "daap.songbookmark"}, {"asbr", DMAP_UINT, 0, "daap.songbitrate"}, {"asbt", DMAP_UINT, 0, "daap.songbeatsperminute"}, + {"ascd", DMAP_UINT, 0, "daap.songcodectype"}, {"ascm", DMAP_STR, 0, "daap.songcomment"}, {"ascn", DMAP_STR, 0, "daap.songcontentdescription"}, + {"asco", DMAP_UINT, 0, "daap.songcompilation"}, {"ascp", DMAP_STR, 0, "daap.songcomposer"}, {"ascr", DMAP_UINT, 0, "daap.songcontentrating"}, + {"ascs", DMAP_UINT, 0, "daap.songcodecsubtype"}, {"asct", DMAP_STR, 0, "daap.songcategory"}, {"asda", DMAP_DATE, 0, "daap.songdateadded"}, + {"asdb", DMAP_UINT, 0, "daap.songdisabled"}, {"asdc", DMAP_UINT, 0, "daap.songdisccount"}, {"asdk", DMAP_UINT, 0, "daap.songdatakind"}, + {"asdm", DMAP_DATE, 0, "daap.songdatemodified"}, {"asdn", DMAP_UINT, 0, "daap.songdiscnumber"}, {"asdp", DMAP_DATE, 0, "daap.songdatepurchased"}, + {"asdr", DMAP_DATE, 0, "daap.songdatereleased"}, {"asdt", DMAP_STR, 0, "daap.songdescription"}, {"ased", DMAP_UINT, 0, "daap.songextradata"}, + {"aseq", DMAP_STR, 0, "daap.songeqpreset"}, {"ases", DMAP_UINT, 0, "daap.songexcludefromshuffle"}, {"asfm", DMAP_STR, 0, "daap.songformat"}, + {"asgn", DMAP_STR, 0, "daap.songgenre"}, {"asgp", DMAP_UINT, 0, "daap.songgapless"}, {"asgr", DMAP_UINT, 0, "daap.supportsgroups"}, + {"ashp", DMAP_UINT, 0, "daap.songhasbeenplayed"}, {"askd", DMAP_DATE, 0, "daap.songlastskipdate"}, + {"askp", DMAP_UINT, 0, "daap.songuserskipcount"}, {"asky", DMAP_STR, 0, "daap.songkeywords"}, + {"aslc", DMAP_STR, 0, "daap.songlongcontentdescription"}, {"aslr", DMAP_UINT, 0, "daap.songalbumuserrating"}, + {"asls", DMAP_UINT, 0, "daap.songlongsize"}, {"aspc", DMAP_UINT, 0, "daap.songuserplaycount"}, {"aspl", DMAP_DATE, 0, "daap.songdateplayed"}, + {"aspu", DMAP_STR, 0, "daap.songpodcasturl"}, {"asri", DMAP_UINT, 0, "daap.songartistid"}, {"asrs", DMAP_UINT, 0, "daap.songuserratingstatus"}, + {"asrv", DMAP_INT, 0, "daap.songrelativevolume"}, {"assa", DMAP_STR, 0, "daap.sortartist"}, {"assc", DMAP_STR, 0, "daap.sortcomposer"}, + {"assl", DMAP_STR, 0, "daap.sortalbumartist"}, {"assn", DMAP_STR, 0, "daap.sortname"}, {"assp", DMAP_UINT, 0, "daap.songstoptime"}, + {"assr", DMAP_UINT, 0, "daap.songsamplerate"}, {"asss", DMAP_STR, 0, "daap.sortseriesname"}, {"asst", DMAP_UINT, 0, "daap.songstarttime"}, + {"assu", DMAP_STR, 0, "daap.sortalbum"}, {"assz", DMAP_UINT, 0, "daap.songsize"}, {"astc", DMAP_UINT, 0, "daap.songtrackcount"}, + {"astm", DMAP_UINT, 0, "daap.songtime"}, {"astn", DMAP_UINT, 0, "daap.songtracknumber"}, {"asul", DMAP_STR, 0, "daap.songdataurl"}, + {"asur", DMAP_UINT, 0, "daap.songuserrating"}, {"asvc", DMAP_UINT, 0, "daap.songprimaryvideocodec"}, {"asyr", DMAP_UINT, 0, "daap.songyear"}, + {"ated", DMAP_UINT, 0, "daap.supportsextradata"}, {"avdb", DMAP_DICT, 0, "daap.serverdatabases"}, {"awrk", DMAP_STR, 0, "daap.songwork"}, + {"caar", DMAP_UINT, 0, "dacp.availablerepeatstates"}, {"caas", DMAP_UINT, 0, "dacp.availableshufflestates"}, {"caci", DMAP_DICT, 0, "caci"}, + {"cafe", DMAP_UINT, 0, "dacp.fullscreenenabled"}, {"cafs", DMAP_UINT, 0, "dacp.fullscreen"}, {"caia", DMAP_UINT, 0, "dacp.isactive"}, + {"cana", DMAP_STR, 0, "dacp.nowplayingartist"}, {"cang", DMAP_STR, 0, "dacp.nowplayinggenre"}, {"canl", DMAP_STR, 0, "dacp.nowplayingalbum"}, + {"cann", DMAP_STR, 0, "dacp.nowplayingname"}, {"canp", DMAP_UINT, 0, "dacp.nowplayingids"}, {"cant", DMAP_UINT, 0, "dacp.nowplayingtime"}, + {"capr", DMAP_VERS, 0, "dacp.protocolversion"}, {"caps", DMAP_UINT, 0, "dacp.playerstate"}, {"carp", DMAP_UINT, 0, "dacp.repeatstate"}, + {"cash", DMAP_UINT, 0, "dacp.shufflestate"}, {"casp", DMAP_DICT, 0, "dacp.speakers"}, {"cast", DMAP_UINT, 0, "dacp.songtime"}, + {"cavc", DMAP_UINT, 0, "dacp.volumecontrollable"}, {"cave", DMAP_UINT, 0, "dacp.visualizerenabled"}, {"cavs", DMAP_UINT, 0, "dacp.visualizer"}, + {"ceJC", DMAP_UINT, 0, "com.apple.itunes.jukebox-client-vote"}, {"ceJI", DMAP_UINT, 0, "com.apple.itunes.jukebox-current"}, + {"ceJS", DMAP_UINT, 0, "com.apple.itunes.jukebox-score"}, {"ceJV", DMAP_UINT, 0, "com.apple.itunes.jukebox-vote"}, + {"ceQR", DMAP_DICT, 0, "com.apple.itunes.playqueue-contents-response"}, {"ceQa", DMAP_STR, 0, "com.apple.itunes.playqueue-album"}, + {"ceQg", DMAP_STR, 0, "com.apple.itunes.playqueue-genre"}, {"ceQn", DMAP_STR, 0, "com.apple.itunes.playqueue-name"}, + {"ceQr", DMAP_STR, 0, "com.apple.itunes.playqueue-artist"}, {"cmgt", DMAP_DICT, 0, "dmcp.getpropertyresponse"}, + {"cmmk", DMAP_UINT, 0, "dmcp.mediakind"}, {"cmpr", DMAP_VERS, 0, "dmcp.protocolversion"}, {"cmsr", DMAP_UINT, 0, "dmcp.serverrevision"}, + {"cmst", DMAP_DICT, 0, "dmcp.playstatus"}, {"cmvo", DMAP_UINT, 0, "dmcp.volume"}, {"f\215ch", DMAP_UINT, 0, "dmap.haschildcontainers"}, + {"ipsa", DMAP_DICT, 0, "dpap.iphotoslideshowadvancedoptions"}, {"ipsl", DMAP_DICT, 0, "dpap.iphotoslideshowoptions"}, + {"mbcl", DMAP_DICT, 0, "dmap.bag"}, {"mccr", DMAP_DICT, 0, "dmap.contentcodesresponse"}, {"mcna", DMAP_STR, 0, "dmap.contentcodesname"}, + {"mcnm", DMAP_UINT, 0, "dmap.contentcodesnumber"}, {"mcon", DMAP_DICT, 0, "dmap.container"}, {"mctc", DMAP_UINT, 0, "dmap.containercount"}, + {"mcti", DMAP_UINT, 0, "dmap.containeritemid"}, {"mcty", DMAP_UINT, 0, "dmap.contentcodestype"}, {"mdbk", DMAP_UINT, 0, "dmap.databasekind"}, + {"mdcl", DMAP_DICT, 0, "dmap.dictionary"}, {"mdst", DMAP_UINT, 0, "dmap.downloadstatus"}, {"meds", DMAP_UINT, 0, "dmap.editcommandssupported"}, + {"meia", DMAP_UINT, 0, "dmap.itemdateadded"}, {"meip", DMAP_UINT, 0, "dmap.itemdateplayed"}, {"mext", DMAP_UINT, 0, "dmap.objectextradata"}, + {"miid", DMAP_UINT, 0, "dmap.itemid"}, {"mikd", DMAP_UINT, 0, "dmap.itemkind"}, {"mimc", DMAP_UINT, 0, "dmap.itemcount"}, #endif - { "minm", DMAP_STR, 0, "dmap.itemname" }, + {"minm", DMAP_STR, 0, "dmap.itemname"}, #ifdef DMAP_FULL - { "mlcl", DMAP_DICT, DMAP_DICT, "dmap.listing" }, - { "mlid", DMAP_UINT, 0, "dmap.sessionid" }, - { "mlit", DMAP_ITEM, 0, "dmap.listingitem" }, - { "mlog", DMAP_DICT, 0, "dmap.loginresponse" }, - { "mpco", DMAP_UINT, 0, "dmap.parentcontainerid" }, - { "mper", DMAP_UINT, 0, "dmap.persistentid" }, - { "mpro", DMAP_VERS, 0, "dmap.protocolversion" }, - { "mrco", DMAP_UINT, 0, "dmap.returnedcount" }, - { "mrpr", DMAP_UINT, 0, "dmap.remotepersistentid" }, - { "msal", DMAP_UINT, 0, "dmap.supportsautologout" }, - { "msas", DMAP_UINT, 0, "dmap.authenticationschemes" }, - { "msau", DMAP_UINT, 0, "dmap.authenticationmethod" }, - { "msbr", DMAP_UINT, 0, "dmap.supportsbrowse" }, - { "msdc", DMAP_UINT, 0, "dmap.databasescount" }, - { "msex", DMAP_UINT, 0, "dmap.supportsextensions" }, - { "msix", DMAP_UINT, 0, "dmap.supportsindex" }, - { "mslr", DMAP_UINT, 0, "dmap.loginrequired" }, - { "msma", DMAP_UINT, 0, "dmap.machineaddress" }, - { "msml", DMAP_DICT, 0, "msml" }, - { "mspi", DMAP_UINT, 0, "dmap.supportspersistentids" }, - { "msqy", DMAP_UINT, 0, "dmap.supportsquery" }, - { "msrs", DMAP_UINT, 0, "dmap.supportsresolve" }, - { "msrv", DMAP_DICT, 0, "dmap.serverinforesponse" }, - { "mstc", DMAP_DATE, 0, "dmap.utctime" }, - { "mstm", DMAP_UINT, 0, "dmap.timeoutinterval" }, - { "msto", DMAP_INT, 0, "dmap.utcoffset" }, - { "msts", DMAP_STR, 0, "dmap.statusstring" }, - { "mstt", DMAP_UINT, 0, "dmap.status" }, - { "msup", DMAP_UINT, 0, "dmap.supportsupdate" }, - { "mtco", DMAP_UINT, 0, "dmap.specifiedtotalcount" }, - { "mudl", DMAP_DICT, 0, "dmap.deletedidlisting" }, - { "mupd", DMAP_DICT, 0, "dmap.updateresponse" }, - { "musr", DMAP_UINT, 0, "dmap.serverrevision" }, - { "muty", DMAP_UINT, 0, "dmap.updatetype" }, - { "pasp", DMAP_STR, 0, "dpap.aspectratio" }, - { "pcmt", DMAP_STR, 0, "dpap.imagecomments" }, - { "peak", DMAP_UINT, 0, "com.apple.itunes.photos.album-kind" }, - { "peed", DMAP_DATE, 0, "com.apple.itunes.photos.exposure-date" }, - { "pefc", DMAP_DICT, 0, "com.apple.itunes.photos.faces" }, - { "peki", DMAP_UINT, 0, "com.apple.itunes.photos.key-image-id" }, - { "pekm", DMAP_DICT, 0, "com.apple.itunes.photos.key-image" }, - { "pemd", DMAP_DATE, 0, "com.apple.itunes.photos.modification-date" }, - { "pfai", DMAP_DICT, 0, "dpap.failureids" }, - { "pfdt", DMAP_DICT, 0, "dpap.filedata" }, - { "pfmt", DMAP_STR, 0, "dpap.imageformat" }, - { "phgt", DMAP_UINT, 0, "dpap.imagepixelheight" }, - { "picd", DMAP_DATE, 0, "dpap.creationdate" }, - { "pifs", DMAP_UINT, 0, "dpap.imagefilesize" }, - { "pimf", DMAP_STR, 0, "dpap.imagefilename" }, - { "plsz", DMAP_UINT, 0, "dpap.imagelargefilesize" }, - { "ppro", DMAP_VERS, 0, "dpap.protocolversion" }, - { "prat", DMAP_UINT, 0, "dpap.imagerating" }, - { "pret", DMAP_DICT, 0, "dpap.retryids" }, - { "pwth", DMAP_UINT, 0, "dpap.imagepixelwidth" } + {"mlcl", DMAP_DICT, DMAP_DICT, "dmap.listing"}, {"mlid", DMAP_UINT, 0, "dmap.sessionid"}, {"mlit", DMAP_ITEM, 0, "dmap.listingitem"}, + {"mlog", DMAP_DICT, 0, "dmap.loginresponse"}, {"mpco", DMAP_UINT, 0, "dmap.parentcontainerid"}, {"mper", DMAP_UINT, 0, "dmap.persistentid"}, + {"mpro", DMAP_VERS, 0, "dmap.protocolversion"}, {"mrco", DMAP_UINT, 0, "dmap.returnedcount"}, {"mrpr", DMAP_UINT, 0, "dmap.remotepersistentid"}, + {"msal", DMAP_UINT, 0, "dmap.supportsautologout"}, {"msas", DMAP_UINT, 0, "dmap.authenticationschemes"}, + {"msau", DMAP_UINT, 0, "dmap.authenticationmethod"}, {"msbr", DMAP_UINT, 0, "dmap.supportsbrowse"}, {"msdc", DMAP_UINT, 0, "dmap.databasescount"}, + {"msex", DMAP_UINT, 0, "dmap.supportsextensions"}, {"msix", DMAP_UINT, 0, "dmap.supportsindex"}, {"mslr", DMAP_UINT, 0, "dmap.loginrequired"}, + {"msma", DMAP_UINT, 0, "dmap.machineaddress"}, {"msml", DMAP_DICT, 0, "msml"}, {"mspi", DMAP_UINT, 0, "dmap.supportspersistentids"}, + {"msqy", DMAP_UINT, 0, "dmap.supportsquery"}, {"msrs", DMAP_UINT, 0, "dmap.supportsresolve"}, {"msrv", DMAP_DICT, 0, "dmap.serverinforesponse"}, + {"mstc", DMAP_DATE, 0, "dmap.utctime"}, {"mstm", DMAP_UINT, 0, "dmap.timeoutinterval"}, {"msto", DMAP_INT, 0, "dmap.utcoffset"}, + {"msts", DMAP_STR, 0, "dmap.statusstring"}, {"mstt", DMAP_UINT, 0, "dmap.status"}, {"msup", DMAP_UINT, 0, "dmap.supportsupdate"}, + {"mtco", DMAP_UINT, 0, "dmap.specifiedtotalcount"}, {"mudl", DMAP_DICT, 0, "dmap.deletedidlisting"}, + {"mupd", DMAP_DICT, 0, "dmap.updateresponse"}, {"musr", DMAP_UINT, 0, "dmap.serverrevision"}, {"muty", DMAP_UINT, 0, "dmap.updatetype"}, + {"pasp", DMAP_STR, 0, "dpap.aspectratio"}, {"pcmt", DMAP_STR, 0, "dpap.imagecomments"}, + {"peak", DMAP_UINT, 0, "com.apple.itunes.photos.album-kind"}, {"peed", DMAP_DATE, 0, "com.apple.itunes.photos.exposure-date"}, + {"pefc", DMAP_DICT, 0, "com.apple.itunes.photos.faces"}, {"peki", DMAP_UINT, 0, "com.apple.itunes.photos.key-image-id"}, + {"pekm", DMAP_DICT, 0, "com.apple.itunes.photos.key-image"}, {"pemd", DMAP_DATE, 0, "com.apple.itunes.photos.modification-date"}, + {"pfai", DMAP_DICT, 0, "dpap.failureids"}, {"pfdt", DMAP_DICT, 0, "dpap.filedata"}, {"pfmt", DMAP_STR, 0, "dpap.imageformat"}, + {"phgt", DMAP_UINT, 0, "dpap.imagepixelheight"}, {"picd", DMAP_DATE, 0, "dpap.creationdate"}, {"pifs", DMAP_UINT, 0, "dpap.imagefilesize"}, + {"pimf", DMAP_STR, 0, "dpap.imagefilename"}, {"plsz", DMAP_UINT, 0, "dpap.imagelargefilesize"}, {"ppro", DMAP_VERS, 0, "dpap.protocolversion"}, + {"prat", DMAP_UINT, 0, "dpap.imagerating"}, {"pret", DMAP_DICT, 0, "dpap.retryids"}, {"pwth", DMAP_UINT, 0, "dpap.imagepixelwidth"} #endif }; static const size_t dmap_field_count = sizeof(dmap_fields) / sizeof(dmap_field); -typedef int (*sort_func) (const void *, const void *); +typedef int (*sort_func)(const void*, const void*); -int dmap_version(void) { - return DMAP_VERSION; +int dmap_version(void) { return DMAP_VERSION; } + +const char* dmap_version_string(void) { + return DMAP_STRINGIFY(DMAP_VERSION_MAJOR) "." DMAP_STRINGIFY(DMAP_VERSION_MINOR) "." DMAP_STRINGIFY(DMAP_VERSION_PATCH); } -const char *dmap_version_string(void) { - return DMAP_STRINGIFY(DMAP_VERSION_MAJOR) "." - DMAP_STRINGIFY(DMAP_VERSION_MINOR) "." - DMAP_STRINGIFY(DMAP_VERSION_PATCH); +static int dmap_field_sort(const dmap_field* a, const dmap_field* b) { return memcmp(a->code, b->code, 4); } + +static const dmap_field* dmap_field_from_code(const char* code) { + dmap_field key; + key.code = code; + return bsearch(&key, dmap_fields, dmap_field_count, sizeof(dmap_field), (sort_func)dmap_field_sort); } -static int dmap_field_sort(const dmap_field *a, const dmap_field *b) { - return memcmp(a->code, b->code, 4); +const char* dmap_name_from_code(const char* code) { + const dmap_field* field; + if(!code) return NULL; + + field = dmap_field_from_code(code); + return field ? field->name : NULL; } -static const dmap_field *dmap_field_from_code(const char *code) { - dmap_field key; - key.code = code; - return bsearch(&key, dmap_fields, dmap_field_count, sizeof(dmap_field), (sort_func)dmap_field_sort); +static uint16_t dmap_read_u16(const char* buf) { return (uint16_t)(((buf[0] & 0xff) << 8) | (buf[1] & 0xff)); } + +static int16_t dmap_read_i16(const char* buf) { return (int16_t)dmap_read_u16(buf); } + +static uint32_t dmap_read_u32(const char* buf) { + return ((uint32_t)(buf[0] & 0xff) << 24) | ((uint32_t)(buf[1] & 0xff) << 16) | ((uint32_t)(buf[2] & 0xff) << 8) | ((uint32_t)(buf[3] & 0xff)); } -const char *dmap_name_from_code(const char *code) { - const dmap_field *field; - if (!code) - return NULL; +static int32_t dmap_read_i32(const char* buf) { return (int32_t)dmap_read_u32(buf); } - field = dmap_field_from_code(code); - return field ? field->name : NULL; +static uint64_t dmap_read_u64(const char* buf) { + return ((uint64_t)(buf[0] & 0xff) << 56) | ((uint64_t)(buf[1] & 0xff) << 48) | ((uint64_t)(buf[2] & 0xff) << 40) | + ((uint64_t)(buf[3] & 0xff) << 32) | ((uint64_t)(buf[4] & 0xff) << 24) | ((uint64_t)(buf[5] & 0xff) << 16) | + ((uint64_t)(buf[6] & 0xff) << 8) | ((uint64_t)(buf[7] & 0xff)); } -static uint16_t dmap_read_u16(const char *buf) { - return (uint16_t)(((buf[0] & 0xff) << 8) | (buf[1] & 0xff)); -} +static int64_t dmap_read_i64(const char* buf) { return (int64_t)dmap_read_u64(buf); } -static int16_t dmap_read_i16(const char *buf) { - return (int16_t)dmap_read_u16(buf); -} +static int dmap_parse_internal(const dmap_settings* settings, const char* buf, size_t len, const dmap_field* parent) { + const dmap_field* field; + DMAP_TYPE field_type; + size_t field_len; + const char* field_name; + const char* p = buf; + const char* end = buf + len; + char code[5] = {0}; -static uint32_t dmap_read_u32(const char *buf) { - return ((uint32_t)(buf[0] & 0xff) << 24) | - ((uint32_t)(buf[1] & 0xff) << 16) | - ((uint32_t)(buf[2] & 0xff) << 8) | - ((uint32_t)(buf[3] & 0xff)); -} + if(!settings || !buf) return -1; -static int32_t dmap_read_i32(const char *buf) { - return (int32_t)dmap_read_u32(buf); -} + while(end - p >= 8) { + memcpy(code, p, 4); + field = dmap_field_from_code(code); + p += 4; -static uint64_t dmap_read_u64(const char *buf) { - return ((uint64_t)(buf[0] & 0xff) << 56) | - ((uint64_t)(buf[1] & 0xff) << 48) | - ((uint64_t)(buf[2] & 0xff) << 40) | - ((uint64_t)(buf[3] & 0xff) << 32) | - ((uint64_t)(buf[4] & 0xff) << 24) | - ((uint64_t)(buf[5] & 0xff) << 16) | - ((uint64_t)(buf[6] & 0xff) << 8) | - ((uint64_t)(buf[7] & 0xff)); -} + field_len = dmap_read_u32(p); + p += 4; -static int64_t dmap_read_i64(const char *buf) { - return (int64_t)dmap_read_u64(buf); -} + if(p + field_len > end) return -1; -static int dmap_parse_internal(const dmap_settings *settings, const char *buf, size_t len, const dmap_field *parent) { - const dmap_field *field; - DMAP_TYPE field_type; - size_t field_len; - const char *field_name; - const char *p = buf; - const char *end = buf + len; - char code[5] = {0}; + if(field) { + field_type = field->type; + field_name = field->name; - if (!settings || !buf) - return -1; + if(field_type == DMAP_ITEM) { + if(parent != NULL && parent->list_item_type) { + field_type = parent->list_item_type; + } else { + field_type = DMAP_DICT; + } + } + } else { + /* Make a best guess of the type */ + field_type = DMAP_UNKNOWN; + field_name = code; - while (end - p >= 8) { - memcpy(code, p, 4); - field = dmap_field_from_code(code); - p += 4; - - field_len = dmap_read_u32(p); - p += 4; - - if (p + field_len > end) - return -1; - - if (field) { - field_type = field->type; - field_name = field->name; - - if (field_type == DMAP_ITEM) { - if (parent != NULL && parent->list_item_type) { - field_type = parent->list_item_type; - } else { - field_type = DMAP_DICT; - } - } - } else { - /* Make a best guess of the type */ - field_type = DMAP_UNKNOWN; - field_name = code; - - if (field_len >= 8) { - /* Look for a four char code followed by a length within the current field */ - if (isalpha(p[0] & 0xff) && - isalpha(p[1] & 0xff) && - isalpha(p[2] & 0xff) && - isalpha(p[3] & 0xff)) { - if (dmap_read_u32(p + 4) < field_len) - field_type = DMAP_DICT; - } - } + if(field_len >= 8) { + /* Look for a four char code followed by a length within the current field */ + if(isalpha(p[0] & 0xff) && isalpha(p[1] & 0xff) && isalpha(p[2] & 0xff) && isalpha(p[3] & 0xff)) { + if(dmap_read_u32(p + 4) < field_len) field_type = DMAP_DICT; + } + } #ifdef DMAP_FULL - if (field_type == DMAP_UNKNOWN) { - size_t i; - int is_string = 1; - for (i=0; i < field_len; i++) { - if (!isprint(p[i] & 0xff)) { - is_string = 0; - break; - } - } + if(field_type == DMAP_UNKNOWN) { + size_t i; + int is_string = 1; + for(i = 0; i < field_len; i++) { + if(!isprint(p[i] & 0xff)) { + is_string = 0; + break; + } + } - field_type = is_string ? DMAP_STR : DMAP_UINT; - } + field_type = is_string ? DMAP_STR : DMAP_UINT; + } #endif - } + } - switch (field_type) { - case DMAP_UINT: - /* Determine the integer's type based on its size */ - switch (field_len) { - case 1: - if (settings->on_uint32) - settings->on_uint32(settings->ctx, code, field_name, (unsigned char)*p); - break; - case 2: - if (settings->on_uint32) - settings->on_uint32(settings->ctx, code, field_name, dmap_read_u16(p)); - break; - case 4: - if (settings->on_uint32) - settings->on_uint32(settings->ctx, code, field_name, dmap_read_u32(p)); - break; - case 8: - if (settings->on_uint64) - settings->on_uint64(settings->ctx, code, field_name, dmap_read_u64(p)); - break; - default: - if (settings->on_data) - settings->on_data(settings->ctx, code, field_name, p, field_len); - break; - } - break; - case DMAP_INT: - switch (field_len) { - case 1: - if (settings->on_int32) - settings->on_int32(settings->ctx, code, field_name, *p); - break; - case 2: - if (settings->on_int32) - settings->on_int32(settings->ctx, code, field_name, dmap_read_i16(p)); - break; - case 4: - if (settings->on_int32) - settings->on_int32(settings->ctx, code, field_name, dmap_read_i32(p)); - break; - case 8: - if (settings->on_int64) - settings->on_int64(settings->ctx, code, field_name, dmap_read_i64(p)); - break; - default: - if (settings->on_data) - settings->on_data(settings->ctx, code, field_name, p, field_len); - break; - } - break; - case DMAP_STR: - if (settings->on_string) - settings->on_string(settings->ctx, code, field_name, p, field_len); - break; - case DMAP_DATA: - if (settings->on_data) - settings->on_data(settings->ctx, code, field_name, p, field_len); - break; - case DMAP_DATE: - /* Seconds since epoch */ - if (settings->on_date) - settings->on_date(settings->ctx, code, field_name, dmap_read_u32(p)); - break; - case DMAP_VERS: - if (settings->on_string && field_len >= 4) { - char version[20]; - sprintf(version, "%u.%u", dmap_read_u16(p), dmap_read_u16(p+2)); - settings->on_string(settings->ctx, code, field_name, version, strlen(version)); - } - break; - case DMAP_DICT: - if (settings->on_dict_start) - settings->on_dict_start(settings->ctx, code, field_name); - if (dmap_parse_internal(settings, p, field_len, field) != 0) - return -1; - if (settings->on_dict_end) - settings->on_dict_end(settings->ctx, code, field_name); - break; - case DMAP_ITEM: - /* Unreachable: listing item types are always mapped to another type */ - abort(); - case DMAP_UNKNOWN: - break; - } + switch(field_type) { + case DMAP_UINT: + /* Determine the integer's type based on its size */ + switch(field_len) { + case 1: + if(settings->on_uint32) settings->on_uint32(settings->ctx, code, field_name, (unsigned char)*p); + break; + case 2: + if(settings->on_uint32) settings->on_uint32(settings->ctx, code, field_name, dmap_read_u16(p)); + break; + case 4: + if(settings->on_uint32) settings->on_uint32(settings->ctx, code, field_name, dmap_read_u32(p)); + break; + case 8: + if(settings->on_uint64) settings->on_uint64(settings->ctx, code, field_name, dmap_read_u64(p)); + break; + default: + if(settings->on_data) settings->on_data(settings->ctx, code, field_name, p, field_len); + break; + } + break; + case DMAP_INT: + switch(field_len) { + case 1: + if(settings->on_int32) settings->on_int32(settings->ctx, code, field_name, *p); + break; + case 2: + if(settings->on_int32) settings->on_int32(settings->ctx, code, field_name, dmap_read_i16(p)); + break; + case 4: + if(settings->on_int32) settings->on_int32(settings->ctx, code, field_name, dmap_read_i32(p)); + break; + case 8: + if(settings->on_int64) settings->on_int64(settings->ctx, code, field_name, dmap_read_i64(p)); + break; + default: + if(settings->on_data) settings->on_data(settings->ctx, code, field_name, p, field_len); + break; + } + break; + case DMAP_STR: + if(settings->on_string) settings->on_string(settings->ctx, code, field_name, p, field_len); + break; + case DMAP_DATA: + if(settings->on_data) settings->on_data(settings->ctx, code, field_name, p, field_len); + break; + case DMAP_DATE: + /* Seconds since epoch */ + if(settings->on_date) settings->on_date(settings->ctx, code, field_name, dmap_read_u32(p)); + break; + case DMAP_VERS: + if(settings->on_string && field_len >= 4) { + char version[20]; + sprintf(version, "%u.%u", dmap_read_u16(p), dmap_read_u16(p + 2)); + settings->on_string(settings->ctx, code, field_name, version, strlen(version)); + } + break; + case DMAP_DICT: + if(settings->on_dict_start) settings->on_dict_start(settings->ctx, code, field_name); + if(dmap_parse_internal(settings, p, field_len, field) != 0) return -1; + if(settings->on_dict_end) settings->on_dict_end(settings->ctx, code, field_name); + break; + case DMAP_ITEM: + /* Unreachable: listing item types are always mapped to another type */ + abort(); + case DMAP_UNKNOWN: + break; + } - p += field_len; - } + p += field_len; + } - if (p != end) - return -1; + if(p != end) return -1; - return 0; + return 0; } -int dmap_parse(const dmap_settings *settings, const char *buf, size_t len) { - return dmap_parse_internal(settings, buf, len, NULL); -} +int dmap_parse(const dmap_settings* settings, const char* buf, size_t len) { return dmap_parse_internal(settings, buf, len, NULL); } diff --git a/components/raop/dmap_parser.h b/components/raop/dmap_parser.h index bf6f31a1..0487d7df 100644 --- a/components/raop/dmap_parser.h +++ b/components/raop/dmap_parser.h @@ -12,9 +12,7 @@ extern "C" { #define DMAP_VERSION_MINOR 2 #define DMAP_VERSION_PATCH 1 -#define DMAP_VERSION (DMAP_VERSION_MAJOR * 1000000 + \ - DMAP_VERSION_MINOR * 1000 + \ - DMAP_VERSION_PATCH) +#define DMAP_VERSION (DMAP_VERSION_MAJOR * 1000000 + DMAP_VERSION_MINOR * 1000 + DMAP_VERSION_PATCH) /* * Callbacks invoked during parsing. @@ -25,29 +23,29 @@ extern "C" { * no known name this parameter contains the same value as the code * parameter. */ -typedef void (*dmap_dict_cb) (void *ctx, const char *code, const char *name); -typedef void (*dmap_int32_cb) (void *ctx, const char *code, const char *name, int32_t value); -typedef void (*dmap_int64_cb) (void *ctx, const char *code, const char *name, int64_t value); -typedef void (*dmap_uint32_cb) (void *ctx, const char *code, const char *name, uint32_t value); -typedef void (*dmap_uint64_cb) (void *ctx, const char *code, const char *name, uint64_t value); -typedef void (*dmap_data_cb) (void *ctx, const char *code, const char *name, const char *buf, size_t len); +typedef void (*dmap_dict_cb)(void* ctx, const char* code, const char* name); +typedef void (*dmap_int32_cb)(void* ctx, const char* code, const char* name, int32_t value); +typedef void (*dmap_int64_cb)(void* ctx, const char* code, const char* name, int64_t value); +typedef void (*dmap_uint32_cb)(void* ctx, const char* code, const char* name, uint32_t value); +typedef void (*dmap_uint64_cb)(void* ctx, const char* code, const char* name, uint64_t value); +typedef void (*dmap_data_cb)(void* ctx, const char* code, const char* name, const char* buf, size_t len); typedef struct { - /* Callbacks to indicate the start and end of dictionary fields. */ - dmap_dict_cb on_dict_start; - dmap_dict_cb on_dict_end; + /* Callbacks to indicate the start and end of dictionary fields. */ + dmap_dict_cb on_dict_start; + dmap_dict_cb on_dict_end; - /* Callbacks for field data. */ - dmap_int32_cb on_int32; - dmap_int64_cb on_int64; - dmap_uint32_cb on_uint32; - dmap_uint64_cb on_uint64; - dmap_uint32_cb on_date; - dmap_data_cb on_string; - dmap_data_cb on_data; + /* Callbacks for field data. */ + dmap_int32_cb on_int32; + dmap_int64_cb on_int64; + dmap_uint32_cb on_uint32; + dmap_uint64_cb on_uint64; + dmap_uint32_cb on_date; + dmap_data_cb on_string; + dmap_data_cb on_data; - /** A context pointer passed to each callback function. */ - void *ctx; + /** A context pointer passed to each callback function. */ + void* ctx; } dmap_settings; /** @@ -61,7 +59,7 @@ int dmap_version(void); /** * Returns the library version as a string. */ -const char *dmap_version_string(void); +const char* dmap_version_string(void); /** * Returns the name associated with the provided content code, or NULL if there @@ -69,7 +67,7 @@ const char *dmap_version_string(void); * * For example, if given the code "minm" this function returns "dmap.itemname". */ -const char *dmap_name_from_code(const char *code); +const char* dmap_name_from_code(const char* code); /** * Parses a DMAP message buffer using the provided settings. @@ -82,7 +80,7 @@ const char *dmap_name_from_code(const char *code); * * @return 0 if parsing was successful, or -1 if an error occurred. */ -int dmap_parse(const dmap_settings *settings, const char *buf, size_t len); +int dmap_parse(const dmap_settings* settings, const char* buf, size_t len); #ifdef __cplusplus } diff --git a/components/raop/log_util.h b/components/raop/log_util.h index 3075dea6..75b0d324 100644 --- a/components/raop/log_util.h +++ b/components/raop/log_util.h @@ -26,15 +26,19 @@ typedef enum { lERROR = 0, lWARN, lINFO, lDEBUG, lSDEBUG } log_level; -const char *logtime(void); -void logprint(const char *fmt, ...); -log_level debug2level(char *level); -char *level2debug(log_level level); +const char* logtime(void); +void logprint(const char* fmt, ...); +log_level debug2level(char* level); +char* level2debug(log_level level); #define LOG_ERROR(fmt, ...) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define LOG_WARN(fmt, ...) if (*loglevel >= lWARN) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define LOG_INFO(fmt, ...) if (*loglevel >= lINFO) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define LOG_DEBUG(fmt, ...) if (*loglevel >= lDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define LOG_SDEBUG(fmt, ...) if (*loglevel >= lSDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define LOG_WARN(fmt, ...) \ + if(*loglevel >= lWARN) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define LOG_INFO(fmt, ...) \ + if(*loglevel >= lINFO) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define LOG_DEBUG(fmt, ...) \ + if(*loglevel >= lDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define LOG_SDEBUG(fmt, ...) \ + if(*loglevel >= lSDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__) #endif \ No newline at end of file diff --git a/components/raop/platform.h b/components/raop/platform.h index b6cc2062..04a7e75a 100644 --- a/components/raop/platform.h +++ b/components/raop/platform.h @@ -12,11 +12,11 @@ #define __PLATFORM_H #ifdef WIN32 -#define LINUX 0 -#define WIN 1 +#define LINUX 0 +#define WIN 1 #else -#define LINUX 1 -#define WIN 0 +#define LINUX 1 +#define WIN 0 #endif #include @@ -31,7 +31,7 @@ #include #include -typedef unsigned __int8 u8_t; +typedef unsigned __int8 u8_t; typedef unsigned __int16 u16_t; typedef unsigned __int32 u32_t; typedef unsigned __int64 u64_t; @@ -41,25 +41,26 @@ typedef __int64 s64_t; #define inline __inline -int gettimeofday(struct timeval *tv, struct timezone *tz); -char *strcasestr(const char *haystack, const char *needle); +int gettimeofday(struct timeval* tv, struct timezone* tz); +char* strcasestr(const char* haystack, const char* needle); -#define usleep(x) Sleep((x)/1000) - #define sleep(x) Sleep((x)*1000) -#define last_error() WSAGetLastError() +#define usleep(x) Sleep((x) / 1000) + +#define sleep(x) Sleep((x) * 1000) +#define last_error() WSAGetLastError() #define ERROR_WOULDBLOCK WSAEWOULDBLOCK -#define open _open -#define read _read -#define poll WSAPoll -#define snprintf _snprintf -#define strcasecmp stricmp -#define _random(x) random(x) -#define VALGRIND_MAKE_MEM_DEFINED(x,y) +#define open _open +#define read _read +#define poll WSAPoll +#define snprintf _snprintf +#define strcasecmp stricmp +#define _random(x) random(x) +#define VALGRIND_MAKE_MEM_DEFINED(x, y) #define S_ADDR(X) X.S_un.S_addr -#define in_addr_t u32_t -#define socklen_t int -#define ssize_t int +#define in_addr_t u32_t +#define socklen_t int +#define ssize_t int #define RTLD_NOW 0 @@ -82,21 +83,21 @@ char *strcasestr(const char *haystack, const char *needle); #include #include -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) -typedef int16_t s16_t; -typedef int32_t s32_t; -typedef int64_t s64_t; -typedef uint8_t u8_t; -typedef uint16_t u16_t; -typedef uint32_t u32_t; +typedef int16_t s16_t; +typedef int32_t s32_t; +typedef int64_t s64_t; +typedef uint8_t u8_t; +typedef uint16_t u16_t; +typedef uint32_t u32_t; typedef unsigned long long u64_t; #define last_error() errno #define ERROR_WOULDBLOCK EWOULDBLOCK -char *strlwr(char *str); +char* strlwr(char* str); #define _random(x) random() #define closesocket(s) close(s) #define S_ADDR(X) X.s_addr @@ -104,14 +105,15 @@ char *strlwr(char *str); #endif typedef struct ntp_s { - u32_t seconds; - u32_t fraction; - } ntp_t; + u32_t seconds; + u32_t fraction; -u64_t timeval_to_ntp(struct timeval tv, struct ntp_s *ntp); -u64_t get_ntp(struct ntp_s *ntp); +} ntp_t; + +u64_t timeval_to_ntp(struct timeval tv, struct ntp_s* ntp); +u64_t get_ntp(struct ntp_s* ntp); // we expect somebody to provide the ms clock, system-wide u32_t _gettime_ms_(void); #define gettime_ms _gettime_ms_ -#endif // __PLATFORM +#endif // __PLATFORM diff --git a/components/raop/raop.c b/components/raop/raop.c index 41aeeefc..e402013b 100644 --- a/components/raop/raop.c +++ b/components/raop/raop.c @@ -34,973 +34,949 @@ #include "dmap_parser.h" #include "log_util.h" -#define RTSP_STACK_SIZE (8*1024) -#define SEARCH_STACK_SIZE (3*1024) +#define RTSP_STACK_SIZE (8 * 1024) +#define SEARCH_STACK_SIZE (3 * 1024) typedef struct raop_ctx_s { #ifdef WIN32 - struct mdns_service *svc; - struct mdnsd *svr; + struct mdns_service* svc; + struct mdnsd* svr; #endif - struct in_addr host; // IP of bridge - short unsigned port; // RTSP port for AirPlay - int sock; // socket of the above - struct in_addr peer; // IP of the iDevice (airplay sender) - bool running; + struct in_addr host; // IP of bridge + short unsigned port; // RTSP port for AirPlay + int sock; // socket of the above + struct in_addr peer; // IP of the iDevice (airplay sender) + bool running; #ifdef WIN32 - pthread_t thread; + pthread_t thread; #else - TaskHandle_t thread, joiner; - StaticTask_t *xTaskBuffer; - StackType_t xStack[RTSP_STACK_SIZE] __attribute__ ((aligned (4))); + TaskHandle_t thread, joiner; + StaticTask_t* xTaskBuffer; + StackType_t xStack[RTSP_STACK_SIZE] __attribute__((aligned(4))); #endif - /* + /* Compiler/Execution bug: if this bool is next to 'running', the rtsp_thread loop sees 'running' being set to false from at first execution ... - */ - bool abort; - unsigned char mac[6]; - int latency; - struct { - char *aesiv, *aeskey; - char *fmtp; - } rtsp; - struct rtp_s *rtp; - raop_cmd_cb_t cmd_cb; - raop_data_cb_t data_cb; - struct { - char DACPid[32], id[32]; - struct in_addr host; - u16_t port; - bool running; + */ + bool abort; + unsigned char mac[6]; + int latency; + struct { + char *aesiv, *aeskey; + char* fmtp; + } rtsp; + struct rtp_s* rtp; + raop_cmd_cb_t cmd_cb; + raop_data_cb_t data_cb; + struct { + char DACPid[32], id[32]; + struct in_addr host; + u16_t port; + bool running; #ifdef WIN32 - struct mDNShandle_s *handle; - pthread_t thread; + struct mDNShandle_s* handle; + pthread_t thread; #else - TaskHandle_t thread; - StaticTask_t *xTaskBuffer; - StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));; - SemaphoreHandle_t destroy_mutex; + TaskHandle_t thread; + StaticTask_t* xTaskBuffer; + StackType_t xStack[SEARCH_STACK_SIZE] __attribute__((aligned(4))); + ; + SemaphoreHandle_t destroy_mutex; #endif - } active_remote; - void *owner; + } active_remote; + void* owner; } raop_ctx_t; extern struct mdnsd* glmDNSServer; -extern log_level raop_loglevel; -static log_level *loglevel = &raop_loglevel; +extern log_level raop_loglevel; +static log_level* loglevel = &raop_loglevel; #ifdef WIN32 -static void* rtsp_thread(void *arg); -static void* search_remote(void *args); +static void* rtsp_thread(void* arg); +static void* search_remote(void* args); #else -static void rtsp_thread(void *arg); -static void search_remote(void *args); +static void rtsp_thread(void* arg); +static void search_remote(void* args); #endif -static void cleanup_rtsp(raop_ctx_t *ctx, bool abort); -static bool handle_rtsp(raop_ctx_t *ctx, int sock); - -static char* rsa_apply(unsigned char *input, int inlen, int *outlen, int mode); -static int base64_pad(char *src, char **padded); -static int base64_encode(const void *data, int size, char **str); -static int base64_decode(const char *str, void *data); +static void cleanup_rtsp(raop_ctx_t* ctx, bool abort); +static bool handle_rtsp(raop_ctx_t* ctx, int sock); +static char* rsa_apply(unsigned char* input, int inlen, int* outlen, int mode); +static int base64_pad(char* src, char** padded); +static int base64_encode(const void* data, int size, char** str); +static int base64_decode(const char* str, void* data); extern char private_key[]; - enum { RSA_MODE_KEY, RSA_MODE_AUTH }; -static void on_dmap_string(void *ctx, const char *code, const char *name, const char *buf, size_t len); +enum { RSA_MODE_KEY, RSA_MODE_AUTH }; + +static void on_dmap_string(void* ctx, const char* code, const char* name, const char* buf, size_t len); #ifndef WIN32 -static int raop_mbedtls_rng(void *ctx, unsigned char *output, size_t output_len) { - (void) ctx; - esp_fill_random(output, output_len); - return 0; +static int raop_mbedtls_rng(void* ctx, unsigned char* output, size_t output_len) { + (void)ctx; + esp_fill_random(output, output_len); + return 0; } #endif /*----------------------------------------------------------------------------*/ -struct raop_ctx_s *raop_create(uint32_t host, char *name, - unsigned char mac[6], int latency, - raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) { - struct raop_ctx_s *ctx = malloc(sizeof(struct raop_ctx_s)); - struct sockaddr_in addr; - char id[64]; - #ifdef WIN32 - socklen_t nlen = sizeof(struct sockaddr); - char *txt[] = { "am=airesp32", "tp=UDP", "sm=false", "sv=false", "ek=1", - "et=0,1", "md=0,1,2", "cn=0,1", "ch=2", - "ss=16", "sr=44100", "vn=3", "txtvers=1", - NULL }; +struct raop_ctx_s* raop_create(uint32_t host, char* name, unsigned char mac[6], int latency, raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) { + struct raop_ctx_s* ctx = malloc(sizeof(struct raop_ctx_s)); + struct sockaddr_in addr; + char id[64]; + +#ifdef WIN32 + socklen_t nlen = sizeof(struct sockaddr); + char* txt[] = {"am=airesp32", "tp=UDP", "sm=false", "sv=false", "ek=1", "et=0,1", "md=0,1,2", "cn=0,1", "ch=2", "ss=16", "sr=44100", "vn=3", + "txtvers=1", NULL}; #else - const mdns_txt_item_t txt[] = { - {"am", "airesp32"}, - {"tp", "UDP"}, - {"sm","false"}, - {"sv","false"}, - {"ek","1"}, - {"et","0,1"}, - {"md","0,1,2"}, - {"cn","0,1"}, - {"ch","2"}, - {"ss","16"}, - {"sr","44100"}, - {"vn","3"}, - {"txtvers","1"}, - }; + const mdns_txt_item_t txt[] = { + {"am", "airesp32"}, + {"tp", "UDP"}, + {"sm", "false"}, + {"sv", "false"}, + {"ek", "1"}, + {"et", "0,1"}, + {"md", "0,1,2"}, + {"cn", "0,1"}, + {"ch", "2"}, + {"ss", "16"}, + {"sr", "44100"}, + {"vn", "3"}, + {"txtvers", "1"}, + }; #endif - if (!ctx) return NULL; + if(!ctx) return NULL; - // make sure we have a clean context - memset(ctx, 0, sizeof(raop_ctx_t)); + // make sure we have a clean context + memset(ctx, 0, sizeof(raop_ctx_t)); #ifdef WIN32 - ctx->svr = glmDNSServer; + ctx->svr = glmDNSServer; #endif - ctx->host.s_addr = host; - ctx->sock = socket(AF_INET, SOCK_STREAM, 0); - ctx->cmd_cb = cmd_cb; - ctx->data_cb = data_cb; - ctx->latency = min(latency, 88200); - if (ctx->sock == -1) { - LOG_ERROR("Cannot create listening socket", NULL); - free(ctx); - return NULL; - } + ctx->host.s_addr = host; + ctx->sock = socket(AF_INET, SOCK_STREAM, 0); + ctx->cmd_cb = cmd_cb; + ctx->data_cb = data_cb; + ctx->latency = min(latency, 88200); + if(ctx->sock == -1) { + LOG_ERROR("Cannot create listening socket", NULL); + free(ctx); + return NULL; + } - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = host; - addr.sin_family = AF_INET; + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = host; + addr.sin_family = AF_INET; #ifdef WIN32 - ctx->port = 0; - addr.sin_port = htons(ctx->port); + ctx->port = 0; + addr.sin_port = htons(ctx->port); #else - ctx->port = 5000; - addr.sin_port = htons(ctx->port); + ctx->port = 5000; + addr.sin_port = htons(ctx->port); #endif - if (bind(ctx->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0 || listen(ctx->sock, 1)) { - LOG_ERROR("Cannot bind or listen RTSP listener: %s", strerror(errno)); - closesocket(ctx->sock); - free(ctx); - return NULL; - } + if(bind(ctx->sock, (struct sockaddr*)&addr, sizeof(addr)) < 0 || listen(ctx->sock, 1)) { + LOG_ERROR("Cannot bind or listen RTSP listener: %s", strerror(errno)); + closesocket(ctx->sock); + free(ctx); + return NULL; + } #ifdef WIN32 - getsockname(ctx->sock, (struct sockaddr *) &addr, &nlen); - ctx->port = ntohs(addr.sin_port); -#endif - ctx->running = true; - memcpy(ctx->mac, mac, 6); - snprintf(id, 64, "%02X%02X%02X%02X%02X%02X@%s", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], name); - #ifdef WIN32 - // seems that Windows snprintf does not add NULL char if actual size > max - id[63] = '\0'; - ctx->svc = mdnsd_register_svc(ctx->svr, id, "_raop._tcp.local", ctx->port, NULL, (const char**) txt); - pthread_create(&ctx->thread, NULL, &rtsp_thread, ctx); - #else - LOG_INFO("starting mDNS with %s", id); - mdns_service_add(id, "_raop", "_tcp", ctx->port, (mdns_txt_item_t*) txt, sizeof(txt) / sizeof(mdns_txt_item_t)); - - ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - ctx->thread = xTaskCreateStaticPinnedToCore( (TaskFunction_t) rtsp_thread, "RTSP", RTSP_STACK_SIZE, ctx, - ESP_TASK_PRIO_MIN + 2, ctx->xStack, ctx->xTaskBuffer, CONFIG_PTHREAD_TASK_CORE_DEFAULT); + getsockname(ctx->sock, (struct sockaddr*)&addr, &nlen); + ctx->port = ntohs(addr.sin_port); #endif - return ctx; + ctx->running = true; + + memcpy(ctx->mac, mac, 6); + snprintf(id, 64, "%02X%02X%02X%02X%02X%02X@%s", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], name); + +#ifdef WIN32 + // seems that Windows snprintf does not add NULL char if actual size > max + id[63] = '\0'; + ctx->svc = mdnsd_register_svc(ctx->svr, id, "_raop._tcp.local", ctx->port, NULL, (const char**)txt); + pthread_create(&ctx->thread, NULL, &rtsp_thread, ctx); + +#else + LOG_INFO("starting mDNS with %s", id); + mdns_service_add(id, "_raop", "_tcp", ctx->port, (mdns_txt_item_t*)txt, sizeof(txt) / sizeof(mdns_txt_item_t)); + + ctx->xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + ctx->thread = xTaskCreateStaticPinnedToCore((TaskFunction_t)rtsp_thread, "RTSP", RTSP_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 2, ctx->xStack, + ctx->xTaskBuffer, CONFIG_PTHREAD_TASK_CORE_DEFAULT); +#endif + + return ctx; } /*----------------------------------------------------------------------------*/ -void raop_abort(struct raop_ctx_s *ctx) { - LOG_INFO("[%p]: aborting RTSP session at next select() wakeup", ctx); - ctx->abort = true; -} - -/*----------------------------------------------------------------------------*/ -void raop_delete(struct raop_ctx_s *ctx) { -#ifdef WIN32 - int sock; - struct sockaddr addr; - socklen_t nlen = sizeof(struct sockaddr); -#endif - - if (!ctx) return; - -#ifdef WIN32 - ctx->running = false; - - // wake-up thread by connecting socket, needed for freeBSD - sock = socket(AF_INET, SOCK_STREAM, 0); - getsockname(ctx->sock, (struct sockaddr *) &addr, &nlen); - connect(sock, (struct sockaddr*) &addr, sizeof(addr)); - closesocket(sock); - - pthread_join(ctx->thread, NULL); - rtp_end(ctx->rtp); - - shutdown(ctx->sock, SD_BOTH); - closesocket(ctx->sock); - - // terminate search, but do not reclaim memory of pthread if never launched - if (ctx->active_remote.handle) { - close_mDNS(ctx->active_remote.handle); - pthread_join(ctx->active_remote.thread, NULL); - } - - // stop broadcasting devices - mdns_service_remove(ctx->svr, ctx->svc); - mdnsd_stop(ctx->svr); -#else - // then the RTSP task - ctx->joiner = xTaskGetCurrentTaskHandle(); - ctx->running = false; - - // brute-force exit of accept() - shutdown(ctx->sock, SHUT_RDWR); - closesocket(ctx->sock); - - // wait to make sure LWIP if scheduled (avoid issue with NotifyTake) - vTaskDelay(100 / portTICK_PERIOD_MS); - ulTaskNotifyTake(pdFALSE, portMAX_DELAY); - vTaskDelete(ctx->thread); - SAFE_PTR_FREE(ctx->xTaskBuffer); - - // cleanup all session-created items - cleanup_rtsp(ctx, true); - - mdns_service_remove("_raop", "_tcp"); -#endif - - NFREE(ctx->rtsp.aeskey); - NFREE(ctx->rtsp.aesiv); - NFREE(ctx->rtsp.fmtp); - - free(ctx); +void raop_abort(struct raop_ctx_s* ctx) { + LOG_INFO("[%p]: aborting RTSP session at next select() wakeup", ctx); + ctx->abort = true; } /*----------------------------------------------------------------------------*/ -bool raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param) { - struct sockaddr_in addr; - int sock; - char *command = NULL; +void raop_delete(struct raop_ctx_s* ctx) { +#ifdef WIN32 + int sock; + struct sockaddr addr; + socklen_t nlen = sizeof(struct sockaddr); +#endif + + if(!ctx) return; + +#ifdef WIN32 + ctx->running = false; + + // wake-up thread by connecting socket, needed for freeBSD + sock = socket(AF_INET, SOCK_STREAM, 0); + getsockname(ctx->sock, (struct sockaddr*)&addr, &nlen); + connect(sock, (struct sockaddr*)&addr, sizeof(addr)); + closesocket(sock); + + pthread_join(ctx->thread, NULL); + rtp_end(ctx->rtp); + + shutdown(ctx->sock, SD_BOTH); + closesocket(ctx->sock); + + // terminate search, but do not reclaim memory of pthread if never launched + if(ctx->active_remote.handle) { + close_mDNS(ctx->active_remote.handle); + pthread_join(ctx->active_remote.thread, NULL); + } + + // stop broadcasting devices + mdns_service_remove(ctx->svr, ctx->svc); + mdnsd_stop(ctx->svr); +#else + // then the RTSP task + ctx->joiner = xTaskGetCurrentTaskHandle(); + ctx->running = false; + + // brute-force exit of accept() + shutdown(ctx->sock, SHUT_RDWR); + closesocket(ctx->sock); + + // wait to make sure LWIP if scheduled (avoid issue with NotifyTake) + vTaskDelay(100 / portTICK_PERIOD_MS); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + vTaskDelete(ctx->thread); + SAFE_PTR_FREE(ctx->xTaskBuffer); + + // cleanup all session-created items + cleanup_rtsp(ctx, true); + + mdns_service_remove("_raop", "_tcp"); +#endif + + NFREE(ctx->rtsp.aeskey); + NFREE(ctx->rtsp.aesiv); + NFREE(ctx->rtsp.fmtp); + + free(ctx); +} + +/*----------------------------------------------------------------------------*/ +bool raop_cmd(struct raop_ctx_s* ctx, raop_event_t event, void* param) { + struct sockaddr_in addr; + int sock; + char* command = NULL; bool success = false; - // first notify the remote controller (if any) - switch(event) { - case RAOP_REW: - command = strdup("beginrew"); - break; - case RAOP_FWD: - command = strdup("beginff"); - break; - case RAOP_PREV: - command = strdup("previtem"); - break; - case RAOP_NEXT: - command = strdup("nextitem"); - break; - case RAOP_TOGGLE: - command = strdup("playpause"); - break; - case RAOP_PAUSE: - command = strdup("pause"); - break; - case RAOP_PLAY: - command = strdup("play"); - break; - case RAOP_RESUME: - command = strdup("playresume"); - break; - case RAOP_STOP: - command = strdup("stop"); - break; - case RAOP_VOLUME_UP: - command = strdup("volumeup"); - break; - case RAOP_VOLUME_DOWN: - command = strdup("volumedown"); - break; - case RAOP_VOLUME: { - float Volume = *((float*) param); - Volume = Volume ? (Volume - 1) * 30 : -144; - asprintf(&command,"setproperty?dmcp.device-volume=%0.4lf", Volume); - break; - } - default: - break; - } + // first notify the remote controller (if any) + switch(event) { + case RAOP_REW: + command = strdup("beginrew"); + break; + case RAOP_FWD: + command = strdup("beginff"); + break; + case RAOP_PREV: + command = strdup("previtem"); + break; + case RAOP_NEXT: + command = strdup("nextitem"); + break; + case RAOP_TOGGLE: + command = strdup("playpause"); + break; + case RAOP_PAUSE: + command = strdup("pause"); + break; + case RAOP_PLAY: + command = strdup("play"); + break; + case RAOP_RESUME: + command = strdup("playresume"); + break; + case RAOP_STOP: + command = strdup("stop"); + break; + case RAOP_VOLUME_UP: + command = strdup("volumeup"); + break; + case RAOP_VOLUME_DOWN: + command = strdup("volumedown"); + break; + case RAOP_VOLUME: { + float Volume = *((float*)param); + Volume = Volume ? (Volume - 1) * 30 : -144; + asprintf(&command, "setproperty?dmcp.device-volume=%0.4lf", Volume); + break; + } + default: + break; + } - // no command to send to remote or no remote found yet - if (!command || !ctx->active_remote.port) { - NFREE(command); - return success; - } + // no command to send to remote or no remote found yet + if(!command || !ctx->active_remote.port) { + NFREE(command); + return success; + } - sock = socket(AF_INET, SOCK_STREAM, 0); + sock = socket(AF_INET, SOCK_STREAM, 0); - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = S_ADDR(ctx->active_remote.host); - addr.sin_port = htons(ctx->active_remote.port); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = S_ADDR(ctx->active_remote.host); + addr.sin_port = htons(ctx->active_remote.port); - if (!connect(sock, (struct sockaddr*) &addr, sizeof(addr))) { - char *method, *buf, resp[512] = ""; - int len; - key_data_t headers[4] = { {NULL, NULL} }; + if(!connect(sock, (struct sockaddr*)&addr, sizeof(addr))) { + char *method, *buf, resp[512] = ""; + int len; + key_data_t headers[4] = {{NULL, NULL}}; - asprintf(&method, "GET /ctrl-int/1/%s HTTP/1.0", command); - kd_add(headers, "Active-Remote", ctx->active_remote.id); - kd_add(headers, "Connection", "close"); + asprintf(&method, "GET /ctrl-int/1/%s HTTP/1.0", command); + kd_add(headers, "Active-Remote", ctx->active_remote.id); + kd_add(headers, "Connection", "close"); - buf = http_send(sock, method, headers); - len = recv(sock, resp, 512, 0); - if (len > 0) resp[len-1] = '\0'; - LOG_INFO("[%p]: sending airplay remote\n%s<== received ==>\n%s", ctx, buf, resp); - - NFREE(method); - NFREE(buf); - kd_free(headers); - success = true; - } else { + buf = http_send(sock, method, headers); + len = recv(sock, resp, 512, 0); + if(len > 0) resp[len - 1] = '\0'; + LOG_INFO("[%p]: sending airplay remote\n%s<== received ==>\n%s", ctx, buf, resp); + + NFREE(method); + NFREE(buf); + kd_free(headers); + success = true; + } else { LOG_INFO("[%p]: can't connect to remote for %s", ctx, command); } - free(command); - closesocket(sock); - - return success; + free(command); + closesocket(sock); + + return success; } /*----------------------------------------------------------------------------*/ #ifdef WIN32 -static void *rtsp_thread(void *arg) { +static void* rtsp_thread(void* arg) { #else -static void rtsp_thread(void *arg) { -#endif - raop_ctx_t *ctx = (raop_ctx_t*) arg; - int sock = -1; +static void rtsp_thread(void* arg) { +#endif + raop_ctx_t* ctx = (raop_ctx_t*)arg; + int sock = -1; - while (ctx->running) { - fd_set rfds; - struct timeval timeout = {0, 100*1000}; - int n; - bool res = false; + while(ctx->running) { + fd_set rfds; + struct timeval timeout = {0, 100 * 1000}; + int n; + bool res = false; - if (sock == -1) { - struct sockaddr_in peer; - socklen_t addrlen = sizeof(struct sockaddr_in); + if(sock == -1) { + struct sockaddr_in peer; + socklen_t addrlen = sizeof(struct sockaddr_in); - sock = accept(ctx->sock, (struct sockaddr*) &peer, &addrlen); - ctx->peer.s_addr = peer.sin_addr.s_addr; - ctx->abort = false; + sock = accept(ctx->sock, (struct sockaddr*)&peer, &addrlen); + ctx->peer.s_addr = peer.sin_addr.s_addr; + ctx->abort = false; - if (sock != -1 && ctx->running) { - LOG_INFO("got RTSP connection %u", sock); - } else continue; - } + if(sock != -1 && ctx->running) { + LOG_INFO("got RTSP connection %u", sock); + } else + continue; + } - FD_ZERO(&rfds); - FD_SET(sock, &rfds); + FD_ZERO(&rfds); + FD_SET(sock, &rfds); - n = select(sock + 1, &rfds, NULL, NULL, &timeout); - - if (!n && !ctx->abort) continue; + n = select(sock + 1, &rfds, NULL, NULL, &timeout); - if (n > 0) res = handle_rtsp(ctx, sock); + if(!n && !ctx->abort) continue; - if (n < 0 || !res || ctx->abort) { - cleanup_rtsp(ctx, true); - closesocket(sock); - LOG_INFO("RTSP close %u", sock); - sock = -1; - } - } - - if (sock != -1) closesocket(sock); + if(n > 0) res = handle_rtsp(ctx, sock); + + if(n < 0 || !res || ctx->abort) { + cleanup_rtsp(ctx, true); + closesocket(sock); + LOG_INFO("RTSP close %u", sock); + sock = -1; + } + } + + if(sock != -1) closesocket(sock); #ifndef WIN32 - xTaskNotifyGive(ctx->joiner); - vTaskSuspend(NULL); + xTaskNotifyGive(ctx->joiner); + vTaskSuspend(NULL); #else - return NULL; + return NULL; #endif } - /*----------------------------------------------------------------------------*/ -static bool handle_rtsp(raop_ctx_t *ctx, int sock) -{ - char *buf = NULL, *body = NULL, method[16] = ""; - key_data_t headers[16], resp[8] = { {NULL, NULL} }; - int len; - bool success = true; - - if (!http_parse(sock, method, headers, &body, &len)) { - NFREE(body); - kd_free(headers); - return false; - } - - if (strcmp(method, "OPTIONS")) { - LOG_INFO("[%p]: received %s", ctx, method); - } +static bool handle_rtsp(raop_ctx_t* ctx, int sock) { + char *buf = NULL, *body = NULL, method[16] = ""; + key_data_t headers[16], resp[8] = {{NULL, NULL}}; + int len; + bool success = true; - if ((buf = kd_lookup(headers, "Apple-Challenge")) != NULL) { - int n; - char *buf_pad, *p, *data_b64 = NULL, data[32]; + if(!http_parse(sock, method, headers, &body, &len)) { + NFREE(body); + kd_free(headers); + return false; + } - LOG_INFO("[%p]: challenge %s", ctx, buf); - - // try to re-acquire IP address if we were missing it - if (S_ADDR(ctx->host) == INADDR_ANY) { - S_ADDR(ctx->host) = get_localhost(NULL); - LOG_INFO("[%p]: IP was missing, trying to get it %s", ctx, inet_ntoa(ctx->host)); - } + if(strcmp(method, "OPTIONS")) { LOG_INFO("[%p]: received %s", ctx, method); } - // need to pad the base64 string as apple device don't - base64_pad(buf, &buf_pad); + if((buf = kd_lookup(headers, "Apple-Challenge")) != NULL) { + int n; + char *buf_pad, *p, *data_b64 = NULL, data[32]; - p = data + min(base64_decode(buf_pad, data), 32-10); - p = (char*) memcpy(p, &S_ADDR(ctx->host), 4) + 4; - p = (char*) memcpy(p, ctx->mac, 6) + 6; - memset(p, 0, 32 - (p - data)); - p = rsa_apply((unsigned char*) data, 32, &n, RSA_MODE_AUTH); - n = base64_encode(p, n, &data_b64); + LOG_INFO("[%p]: challenge %s", ctx, buf); - // remove padding as well (seems to be optional now) - for (n = strlen(data_b64) - 1; n > 0 && data_b64[n] == '='; data_b64[n--] = '\0'); + // try to re-acquire IP address if we were missing it + if(S_ADDR(ctx->host) == INADDR_ANY) { + S_ADDR(ctx->host) = get_localhost(NULL); + LOG_INFO("[%p]: IP was missing, trying to get it %s", ctx, inet_ntoa(ctx->host)); + } - kd_add(resp, "Apple-Response", data_b64); + // need to pad the base64 string as apple device don't + base64_pad(buf, &buf_pad); - NFREE(p); - NFREE(buf_pad); - NFREE(data_b64); - } - - if (!strcmp(method, "OPTIONS")) { + p = data + min(base64_decode(buf_pad, data), 32 - 10); + p = (char*)memcpy(p, &S_ADDR(ctx->host), 4) + 4; + p = (char*)memcpy(p, ctx->mac, 6) + 6; + memset(p, 0, 32 - (p - data)); + p = rsa_apply((unsigned char*)data, 32, &n, RSA_MODE_AUTH); + n = base64_encode(p, n, &data_b64); - kd_add(resp, "Public", "ANNOUNCE, SETUP, RECORD, PAUSE, FLUSH, TEARDOWN, OPTIONS, GET_PARAMETER, SET_PARAMETER"); + // remove padding as well (seems to be optional now) + for(n = strlen(data_b64) - 1; n > 0 && data_b64[n] == '='; data_b64[n--] = '\0'); - } else if (!strcmp(method, "ANNOUNCE")) { - char *padded, *p; + kd_add(resp, "Apple-Response", data_b64); - NFREE(ctx->rtsp.aeskey); - NFREE(ctx->rtsp.aesiv); - NFREE(ctx->rtsp.fmtp); + NFREE(p); + NFREE(buf_pad); + NFREE(data_b64); + } - if ((p = strcasestr(body, "rsaaeskey")) != NULL) { - unsigned char *aeskey; - int len, outlen; + if(!strcmp(method, "OPTIONS")) { - p = strextract(p, ":", "\r\n"); - base64_pad(p, &padded); - aeskey = malloc(strlen(padded)); - len = base64_decode(padded, aeskey); - ctx->rtsp.aeskey = rsa_apply(aeskey, len, &outlen, RSA_MODE_KEY); + kd_add(resp, "Public", "ANNOUNCE, SETUP, RECORD, PAUSE, FLUSH, TEARDOWN, OPTIONS, GET_PARAMETER, SET_PARAMETER"); - NFREE(p); - NFREE(aeskey); - NFREE(padded); - } + } else if(!strcmp(method, "ANNOUNCE")) { + char *padded, *p; - if ((p = strcasestr(body, "aesiv")) != NULL) { - p = strextract(p, ":", "\r\n"); - base64_pad(p, &padded); - ctx->rtsp.aesiv = malloc(strlen(padded)); - base64_decode(padded, ctx->rtsp.aesiv); + NFREE(ctx->rtsp.aeskey); + NFREE(ctx->rtsp.aesiv); + NFREE(ctx->rtsp.fmtp); - NFREE(p); - NFREE(padded); - } + if((p = strcasestr(body, "rsaaeskey")) != NULL) { + unsigned char* aeskey; + int len, outlen; - if ((p = strcasestr(body, "fmtp")) != NULL) { - p = strextract(p, ":", "\r\n"); - ctx->rtsp.fmtp = strdup(p); - NFREE(p); - } + p = strextract(p, ":", "\r\n"); + base64_pad(p, &padded); + aeskey = malloc(strlen(padded)); + len = base64_decode(padded, aeskey); + ctx->rtsp.aeskey = rsa_apply(aeskey, len, &outlen, RSA_MODE_KEY); - // on announce, search remote - if ((buf = kd_lookup(headers, "DACP-ID")) != NULL) strcpy(ctx->active_remote.DACPid, buf); - if ((buf = kd_lookup(headers, "Active-Remote")) != NULL) strcpy(ctx->active_remote.id, buf); + NFREE(p); + NFREE(aeskey); + NFREE(padded); + } -#ifdef WIN32 - ctx->active_remote.handle = init_mDNS(false, ctx->host); - pthread_create(&ctx->active_remote.thread, NULL, &search_remote, ctx); + if((p = strcasestr(body, "aesiv")) != NULL) { + p = strextract(p, ":", "\r\n"); + base64_pad(p, &padded); + ctx->rtsp.aesiv = malloc(strlen(padded)); + base64_decode(padded, ctx->rtsp.aesiv); + + NFREE(p); + NFREE(padded); + } + + if((p = strcasestr(body, "fmtp")) != NULL) { + p = strextract(p, ":", "\r\n"); + ctx->rtsp.fmtp = strdup(p); + NFREE(p); + } + + // on announce, search remote + if((buf = kd_lookup(headers, "DACP-ID")) != NULL) strcpy(ctx->active_remote.DACPid, buf); + if((buf = kd_lookup(headers, "Active-Remote")) != NULL) strcpy(ctx->active_remote.id, buf); + +#ifdef WIN32 + ctx->active_remote.handle = init_mDNS(false, ctx->host); + pthread_create(&ctx->active_remote.thread, NULL, &search_remote, ctx); #else - ctx->active_remote.running = true; - ctx->active_remote.destroy_mutex = xSemaphoreCreateBinary(); - ctx->active_remote.xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - ctx->active_remote.thread = xTaskCreateStaticPinnedToCore( (TaskFunction_t) search_remote, "search_remote", SEARCH_STACK_SIZE, ctx, - ESP_TASK_PRIO_MIN + 2, ctx->active_remote.xStack, ctx->active_remote.xTaskBuffer, - CONFIG_PTHREAD_TASK_CORE_DEFAULT ); -#endif + ctx->active_remote.running = true; + ctx->active_remote.destroy_mutex = xSemaphoreCreateBinary(); + ctx->active_remote.xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + ctx->active_remote.thread = xTaskCreateStaticPinnedToCore((TaskFunction_t)search_remote, "search_remote", SEARCH_STACK_SIZE, ctx, + ESP_TASK_PRIO_MIN + 2, ctx->active_remote.xStack, ctx->active_remote.xTaskBuffer, CONFIG_PTHREAD_TASK_CORE_DEFAULT); +#endif - } else if (!strcmp(method, "SETUP") && ((buf = kd_lookup(headers, "Transport")) != NULL)) { - char *p; - rtp_resp_t rtp = { 0 }; - short unsigned tport = 0, cport = 0; - uint8_t *buffer = NULL; - size_t size = 0; + } else if(!strcmp(method, "SETUP") && ((buf = kd_lookup(headers, "Transport")) != NULL)) { + char* p; + rtp_resp_t rtp = {0}; + short unsigned tport = 0, cport = 0; + uint8_t* buffer = NULL; + size_t size = 0; - // we are about to stream, do something if needed and optionally give buffers to play with - success = ctx->cmd_cb(RAOP_SETUP, &buffer, &size); + // we are about to stream, do something if needed and optionally give buffers to play with + success = ctx->cmd_cb(RAOP_SETUP, &buffer, &size); - if ((p = strcasestr(buf, "timing_port")) != NULL) sscanf(p, "%*[^=]=%hu", &tport); - if ((p = strcasestr(buf, "control_port")) != NULL) sscanf(p, "%*[^=]=%hu", &cport); + if((p = strcasestr(buf, "timing_port")) != NULL) sscanf(p, "%*[^=]=%hu", &tport); + if((p = strcasestr(buf, "control_port")) != NULL) sscanf(p, "%*[^=]=%hu", &cport); - rtp = rtp_init(ctx->peer, ctx->latency, ctx->rtsp.aeskey, ctx->rtsp.aesiv, - ctx->rtsp.fmtp, cport, tport, buffer, size, ctx->cmd_cb, ctx->data_cb); - - ctx->rtp = rtp.ctx; - - if ( (cport * tport * rtp.cport * rtp.tport * rtp.aport) != 0 && rtp.ctx) { - char *transport; - asprintf(&transport, "RTP/AVP/UDP;unicast;mode=record;control_port=%u;timing_port=%u;server_port=%u", rtp.cport, rtp.tport, rtp.aport); - LOG_DEBUG("[%p]: audio=(%hu:%hu), timing=(%hu:%hu), control=(%hu:%hu)", ctx, 0, rtp.aport, tport, rtp.tport, cport, rtp.cport); - kd_add(resp, "Transport", transport); - kd_add(resp, "Session", "DEADBEEF"); - free(transport); - } else { - success = false; - LOG_INFO("[%p]: cannot start session, missing ports", ctx); - } + rtp = rtp_init( + ctx->peer, ctx->latency, ctx->rtsp.aeskey, ctx->rtsp.aesiv, ctx->rtsp.fmtp, cport, tport, buffer, size, ctx->cmd_cb, ctx->data_cb); - } else if (!strcmp(method, "RECORD")) { - unsigned short seqno = 0; - unsigned rtptime = 0; - char *p; + ctx->rtp = rtp.ctx; - if (ctx->latency) { - char latency[6]; - snprintf(latency, 6, "%u", ctx->latency); - kd_add(resp, "Audio-Latency", latency); - } + if((cport * tport * rtp.cport * rtp.tport * rtp.aport) != 0 && rtp.ctx) { + char* transport; + asprintf(&transport, "RTP/AVP/UDP;unicast;mode=record;control_port=%u;timing_port=%u;server_port=%u", rtp.cport, rtp.tport, rtp.aport); + LOG_DEBUG("[%p]: audio=(%hu:%hu), timing=(%hu:%hu), control=(%hu:%hu)", ctx, 0, rtp.aport, tport, rtp.tport, cport, rtp.cport); + kd_add(resp, "Transport", transport); + kd_add(resp, "Session", "DEADBEEF"); + free(transport); + } else { + success = false; + LOG_INFO("[%p]: cannot start session, missing ports", ctx); + } - buf = kd_lookup(headers, "RTP-Info"); - if (buf && (p = strcasestr(buf, "seq")) != NULL) sscanf(p, "%*[^=]=%hu", &seqno); - if (buf && (p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime); + } else if(!strcmp(method, "RECORD")) { + unsigned short seqno = 0; + unsigned rtptime = 0; + char* p; - if (ctx->rtp) rtp_record(ctx->rtp, seqno, rtptime); + if(ctx->latency) { + char latency[6]; + snprintf(latency, 6, "%u", ctx->latency); + kd_add(resp, "Audio-Latency", latency); + } - success = ctx->cmd_cb(RAOP_STREAM); + buf = kd_lookup(headers, "RTP-Info"); + if(buf && (p = strcasestr(buf, "seq")) != NULL) sscanf(p, "%*[^=]=%hu", &seqno); + if(buf && (p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime); - } else if (!strcmp(method, "FLUSH")) { - unsigned short seqno = 0; - unsigned rtptime = 0; - char *p; + if(ctx->rtp) rtp_record(ctx->rtp, seqno, rtptime); - buf = kd_lookup(headers, "RTP-Info"); - if ((p = strcasestr(buf, "seq")) != NULL) sscanf(p, "%*[^=]=%hu", &seqno); - if ((p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime); + success = ctx->cmd_cb(RAOP_STREAM); - // only send FLUSH if useful (discards frames above buffer head and top) - if (ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime, true)) { - success = ctx->cmd_cb(RAOP_FLUSH); - rtp_flush_release(ctx->rtp); - } + } else if(!strcmp(method, "FLUSH")) { + unsigned short seqno = 0; + unsigned rtptime = 0; + char* p; - } else if (!strcmp(method, "TEARDOWN")) { + buf = kd_lookup(headers, "RTP-Info"); + if((p = strcasestr(buf, "seq")) != NULL) sscanf(p, "%*[^=]=%hu", &seqno); + if((p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime); - cleanup_rtsp(ctx, false); - success = ctx->cmd_cb(RAOP_STOP); + // only send FLUSH if useful (discards frames above buffer head and top) + if(ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime, true)) { + success = ctx->cmd_cb(RAOP_FLUSH); + rtp_flush_release(ctx->rtp); + } - } else if (!strcmp(method, "SET_PARAMETER")) { - char *p; + } else if(!strcmp(method, "TEARDOWN")) { - if (body && (p = strcasestr(body, "volume")) != NULL) { - float volume; + cleanup_rtsp(ctx, false); + success = ctx->cmd_cb(RAOP_STOP); - sscanf(p, "%*[^:]:%f", &volume); - LOG_INFO("[%p]: SET PARAMETER volume %f", ctx, volume); - volume = (volume == -144.0) ? 0 : (1 + volume / 30); - success = ctx->cmd_cb(RAOP_VOLUME, volume); - } else if (body && (p = strcasestr(body, "progress")) != NULL) { - int start, current, stop = 0; + } else if(!strcmp(method, "SET_PARAMETER")) { + char* p; - // we want ms, not s - sscanf(p, "%*[^:]:%u/%u/%u", &start, ¤t, &stop); - current = ((current - start) / 44100) * 1000; - if (stop) stop = ((stop - start) / 44100) * 1000; - LOG_INFO("[%p]: SET PARAMETER progress %d/%u %s", ctx, current, stop, p); - success = ctx->cmd_cb(RAOP_PROGRESS, max(current, 0), stop); - } else if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && !strcasecmp(p, "application/x-dmap-tagged")) { - struct metadata_s metadata; - dmap_settings settings = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, on_dmap_string, NULL, - NULL - }; + if(body && (p = strcasestr(body, "volume")) != NULL) { + float volume; - settings.ctx = &metadata; - memset(&metadata, 0, sizeof(struct metadata_s)); - if (!dmap_parse(&settings, body, len)) { + sscanf(p, "%*[^:]:%f", &volume); + LOG_INFO("[%p]: SET PARAMETER volume %f", ctx, volume); + volume = (volume == -144.0) ? 0 : (1 + volume / 30); + success = ctx->cmd_cb(RAOP_VOLUME, volume); + } else if(body && (p = strcasestr(body, "progress")) != NULL) { + int start, current, stop = 0; + + // we want ms, not s + sscanf(p, "%*[^:]:%u/%u/%u", &start, ¤t, &stop); + current = ((current - start) / 44100) * 1000; + if(stop) stop = ((stop - start) / 44100) * 1000; + LOG_INFO("[%p]: SET PARAMETER progress %d/%u %s", ctx, current, stop, p); + success = ctx->cmd_cb(RAOP_PROGRESS, max(current, 0), stop); + } else if(body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && !strcasecmp(p, "application/x-dmap-tagged")) { + struct metadata_s metadata; + dmap_settings settings = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, on_dmap_string, NULL, NULL}; + + settings.ctx = &metadata; + memset(&metadata, 0, sizeof(struct metadata_s)); + if(!dmap_parse(&settings, body, len)) { unsigned timestamp = 0; - if ((p = kd_lookup(headers, "RTP-Info")) != NULL) sscanf(p, "%*[^=]=%u", ×tamp); - LOG_INFO("[%p]: received metadata (ts: %d)\n\tartist: %s\n\talbum: %s\n\ttitle: %s", - ctx, timestamp, metadata.artist ? metadata.artist : "", metadata.album ? metadata.album : "", - metadata.title ? metadata.title : ""); + if((p = kd_lookup(headers, "RTP-Info")) != NULL) sscanf(p, "%*[^=]=%u", ×tamp); + LOG_INFO("[%p]: received metadata (ts: %d)\n\tartist: %s\n\talbum: %s\n\ttitle: %s", ctx, timestamp, + metadata.artist ? metadata.artist : "", metadata.album ? metadata.album : "", metadata.title ? metadata.title : ""); success = ctx->cmd_cb(RAOP_METADATA, metadata.artist, metadata.album, metadata.title, timestamp); - free_metadata(&metadata); - } - } else if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && strcasestr(p, "image/jpeg")) { + free_metadata(&metadata); + } + } else if(body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && strcasestr(p, "image/jpeg")) { unsigned timestamp = 0; - if ((p = kd_lookup(headers, "RTP-Info")) != NULL) sscanf(p, "%*[^=]=%u", ×tamp); - LOG_INFO("[%p]: received JPEG image of %d bytes (ts:%d)", ctx, len, timestamp); - ctx->cmd_cb(RAOP_ARTWORK, body, len, timestamp); - } else { - char *dump = kd_dump(headers); - LOG_INFO("Unhandled SET PARAMETER\n%s", dump); - free(dump); - } - } + if((p = kd_lookup(headers, "RTP-Info")) != NULL) sscanf(p, "%*[^=]=%u", ×tamp); + LOG_INFO("[%p]: received JPEG image of %d bytes (ts:%d)", ctx, len, timestamp); + ctx->cmd_cb(RAOP_ARTWORK, body, len, timestamp); + } else { + char* dump = kd_dump(headers); + LOG_INFO("Unhandled SET PARAMETER\n%s", dump); + free(dump); + } + } - // don't need to free "buf" because kd_lookup return a pointer, not a strdup - kd_add(resp, "Audio-Jack-Status", "connected; type=analog"); - kd_add(resp, "CSeq", kd_lookup(headers, "CSeq")); + // don't need to free "buf" because kd_lookup return a pointer, not a strdup + kd_add(resp, "Audio-Jack-Status", "connected; type=analog"); + kd_add(resp, "CSeq", kd_lookup(headers, "CSeq")); - if (success) { - buf = http_send(sock, "RTSP/1.0 200 OK", resp); - } else { - buf = http_send(sock, "RTSP/1.0 503 ERROR", NULL); - closesocket(sock); - } + if(success) { + buf = http_send(sock, "RTSP/1.0 200 OK", resp); + } else { + buf = http_send(sock, "RTSP/1.0 503 ERROR", NULL); + closesocket(sock); + } - if (strcmp(method, "OPTIONS")) { - LOG_INFO("[%p]: responding:\n%s", ctx, buf ? buf : ""); - } + if(strcmp(method, "OPTIONS")) { LOG_INFO("[%p]: responding:\n%s", ctx, buf ? buf : ""); } - NFREE(body); - NFREE(buf); - kd_free(resp); - kd_free(headers); + NFREE(body); + NFREE(buf); + kd_free(resp); + kd_free(headers); - return true; + return true; } /*----------------------------------------------------------------------------*/ -void cleanup_rtsp(raop_ctx_t *ctx, bool abort) { - // first stop RTP process - if (ctx->rtp) { - rtp_end(ctx->rtp); - ctx->rtp = NULL; - if (abort) LOG_INFO("[%p]: RTP thread aborted", ctx); - } +void cleanup_rtsp(raop_ctx_t* ctx, bool abort) { + // first stop RTP process + if(ctx->rtp) { + rtp_end(ctx->rtp); + ctx->rtp = NULL; + if(abort) LOG_INFO("[%p]: RTP thread aborted", ctx); + } - if (ctx->active_remote.running) { + if(ctx->active_remote.running) { #ifdef WIN32 - pthread_join(ctx->active_remote.thread, NULL); - close_mDNS(ctx->active_remote.handle); + pthread_join(ctx->active_remote.thread, NULL); + close_mDNS(ctx->active_remote.handle); #else - // need to make sure no search is on-going and reclaim task memory - ctx->active_remote.running = false; - xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY); - vTaskDelete(ctx->active_remote.thread); - SAFE_PTR_FREE(ctx->active_remote.xTaskBuffer); - vSemaphoreDelete(ctx->active_remote.destroy_mutex); + // need to make sure no search is on-going and reclaim task memory + ctx->active_remote.running = false; + xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY); + vTaskDelete(ctx->active_remote.thread); + SAFE_PTR_FREE(ctx->active_remote.xTaskBuffer); + vSemaphoreDelete(ctx->active_remote.destroy_mutex); #endif - memset(&ctx->active_remote, 0, sizeof(ctx->active_remote)); - LOG_INFO("[%p]: Remote search thread aborted", ctx); - } + memset(&ctx->active_remote, 0, sizeof(ctx->active_remote)); + LOG_INFO("[%p]: Remote search thread aborted", ctx); + } - NFREE(ctx->rtsp.aeskey); - NFREE(ctx->rtsp.aesiv); - NFREE(ctx->rtsp.fmtp); -} + NFREE(ctx->rtsp.aeskey); + NFREE(ctx->rtsp.aesiv); + NFREE(ctx->rtsp.fmtp); +} /*----------------------------------------------------------------------------*/ #ifdef WIN32 -bool search_remote_cb(mDNSservice_t *slist, void *cookie, bool *stop) { - mDNSservice_t *s; - raop_ctx_t *ctx = (raop_ctx_t*) cookie; +bool search_remote_cb(mDNSservice_t* slist, void* cookie, bool* stop) { + mDNSservice_t* s; + raop_ctx_t* ctx = (raop_ctx_t*)cookie; - // see if we have found an active remote for our ID - for (s = slist; s; s = s->next) { - if (strcasestr(s->name, ctx->active_remote.DACPid)) { - ctx->active_remote.host = s->addr; - ctx->active_remote.port = s->port; - LOG_INFO("[%p]: found ActiveRemote for %s at %s:%u", ctx, ctx->active_remote.DACPid, - inet_ntoa(ctx->active_remote.host), ctx->active_remote.port); - *stop = true; - break; - } - } + // see if we have found an active remote for our ID + for(s = slist; s; s = s->next) { + if(strcasestr(s->name, ctx->active_remote.DACPid)) { + ctx->active_remote.host = s->addr; + ctx->active_remote.port = s->port; + LOG_INFO("[%p]: found ActiveRemote for %s at %s:%u", ctx, ctx->active_remote.DACPid, inet_ntoa(ctx->active_remote.host), + ctx->active_remote.port); + *stop = true; + break; + } + } - // let caller clear list - return false; + // let caller clear list + return false; } - /*----------------------------------------------------------------------------*/ -static void* search_remote(void *args) { - raop_ctx_t *ctx = (raop_ctx_t*) args; +static void* search_remote(void* args) { + raop_ctx_t* ctx = (raop_ctx_t*)args; - query_mDNS(ctx->active_remote.handle, "_dacp._tcp.local", 0, 0, &search_remote_cb, (void*) ctx); + query_mDNS(ctx->active_remote.handle, "_dacp._tcp.local", 0, 0, &search_remote_cb, (void*)ctx); - return NULL; + return NULL; } #else /*----------------------------------------------------------------------------*/ -static void search_remote(void *args) { - raop_ctx_t *ctx = (raop_ctx_t*) args; - bool found = false; - - LOG_INFO("starting remote search"); +static void search_remote(void* args) { + raop_ctx_t* ctx = (raop_ctx_t*)args; + bool found = false; - while (ctx->active_remote.running && !found) { - mdns_result_t *results = NULL; - mdns_result_t *r; - mdns_ip_addr_t *a; + LOG_INFO("starting remote search"); - if (mdns_query_ptr("_dacp", "_tcp", 3000, 32, &results)) { - LOG_ERROR("mDNS active remote query Failed"); - continue; - } + while(ctx->active_remote.running && !found) { + mdns_result_t* results = NULL; + mdns_result_t* r; + mdns_ip_addr_t* a; - for (r = results; r && !strcasestr(r->instance_name, ctx->active_remote.DACPid); r = r->next); - if (r) { - for (a = r->addr; a && a->addr.type != IPADDR_TYPE_V4; a = a->next); - if (a) { - found = true; - ctx->active_remote.host.s_addr = a->addr.u_addr.ip4.addr; - ctx->active_remote.port = r->port; - LOG_INFO("found remote %s %s:%hu", r->instance_name, inet_ntoa(ctx->active_remote.host), ctx->active_remote.port); - } - } + if(mdns_query_ptr("_dacp", "_tcp", 3000, 32, &results)) { + LOG_ERROR("mDNS active remote query Failed"); + continue; + } - mdns_query_results_free(results); - } + for(r = results; r && !strcasestr(r->instance_name, ctx->active_remote.DACPid); r = r->next); + if(r) { + for(a = r->addr; a && a->addr.type != IPADDR_TYPE_V4; a = a->next); + if(a) { + found = true; + ctx->active_remote.host.s_addr = a->addr.u_addr.ip4.addr; + ctx->active_remote.port = r->port; + LOG_INFO("found remote %s %s:%hu", r->instance_name, inet_ntoa(ctx->active_remote.host), ctx->active_remote.port); + } + } - // can't use xNotifyGive as it seems LWIP is using it as well - xSemaphoreGive(ctx->active_remote.destroy_mutex); - vTaskSuspend(NULL); - } + mdns_query_results_free(results); + } + + // can't use xNotifyGive as it seems LWIP is using it as well + xSemaphoreGive(ctx->active_remote.destroy_mutex); + vTaskSuspend(NULL); +} #endif - /*----------------------------------------------------------------------------*/ -static char *rsa_apply(unsigned char *input, int inlen, int *outlen, int mode) -{ - const static char super_secret_key[] = - "-----BEGIN RSA PRIVATE KEY-----\n" - "MIIEpQIBAAKCAQEA59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUt\n" - "wC5vOYvfDmFI6oSFXi5ELabWJmT2dKHzBJKa3k9ok+8t9ucRqMd6DZHJ2YCCLlDRKSKv6kDqnw4U\n" - "wPdpOMXziC/AMj3Z/lUVX1G7WSHCAWKf1zNS1eLvqr+boEjXuBOitnZ/bDzPHrTOZz0Dew0uowxf\n" - "/+sG+NCK3eQJVxqcaJ/vEHKIVd2M+5qL71yJQ+87X6oV3eaYvt3zWZYD6z5vYTcrtij2VZ9Zmni/\n" - "UAaHqn9JdsBWLUEpVviYnhimNVvYFZeCXg/IdTQ+x4IRdiXNv5hEewIDAQABAoIBAQDl8Axy9XfW\n" - "BLmkzkEiqoSwF0PsmVrPzH9KsnwLGH+QZlvjWd8SWYGN7u1507HvhF5N3drJoVU3O14nDY4TFQAa\n" - "LlJ9VM35AApXaLyY1ERrN7u9ALKd2LUwYhM7Km539O4yUFYikE2nIPscEsA5ltpxOgUGCY7b7ez5\n" - "NtD6nL1ZKauw7aNXmVAvmJTcuPxWmoktF3gDJKK2wxZuNGcJE0uFQEG4Z3BrWP7yoNuSK3dii2jm\n" - "lpPHr0O/KnPQtzI3eguhe0TwUem/eYSdyzMyVx/YpwkzwtYL3sR5k0o9rKQLtvLzfAqdBxBurciz\n" - "aaA/L0HIgAmOit1GJA2saMxTVPNhAoGBAPfgv1oeZxgxmotiCcMXFEQEWflzhWYTsXrhUIuz5jFu\n" - "a39GLS99ZEErhLdrwj8rDDViRVJ5skOp9zFvlYAHs0xh92ji1E7V/ysnKBfsMrPkk5KSKPrnjndM\n" - "oPdevWnVkgJ5jxFuNgxkOLMuG9i53B4yMvDTCRiIPMQ++N2iLDaRAoGBAO9v//mU8eVkQaoANf0Z\n" - "oMjW8CN4xwWA2cSEIHkd9AfFkftuv8oyLDCG3ZAf0vrhrrtkrfa7ef+AUb69DNggq4mHQAYBp7L+\n" - "k5DKzJrKuO0r+R0YbY9pZD1+/g9dVt91d6LQNepUE/yY2PP5CNoFmjedpLHMOPFdVgqDzDFxU8hL\n" - "AoGBANDrr7xAJbqBjHVwIzQ4To9pb4BNeqDndk5Qe7fT3+/H1njGaC0/rXE0Qb7q5ySgnsCb3DvA\n" - "cJyRM9SJ7OKlGt0FMSdJD5KG0XPIpAVNwgpXXH5MDJg09KHeh0kXo+QA6viFBi21y340NonnEfdf\n" - "54PX4ZGS/Xac1UK+pLkBB+zRAoGAf0AY3H3qKS2lMEI4bzEFoHeK3G895pDaK3TFBVmD7fV0Zhov\n" - "17fegFPMwOII8MisYm9ZfT2Z0s5Ro3s5rkt+nvLAdfC/PYPKzTLalpGSwomSNYJcB9HNMlmhkGzc\n" - "1JnLYT4iyUyx6pcZBmCd8bD0iwY/FzcgNDaUmbX9+XDvRA0CgYEAkE7pIPlE71qvfJQgoA9em0gI\n" - "LAuE4Pu13aKiJnfft7hIjbK+5kyb3TysZvoyDnb3HOKvInK7vXbKuU4ISgxB2bB3HcYzQMGsz1qJ\n" - "2gG0N5hvJpzwwhbhXqFKA4zaaSrw622wDniAK5MlIE0tIAKKP4yxNGjoD2QYjhBGuhvkWKY=\n" - "-----END RSA PRIVATE KEY-----"; +/*----------------------------------------------------------------------------*/ +static char* rsa_apply(unsigned char* input, int inlen, int* outlen, int mode) { + const static char super_secret_key[] = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEA59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUt\n" + "wC5vOYvfDmFI6oSFXi5ELabWJmT2dKHzBJKa3k9ok+8t9ucRqMd6DZHJ2YCCLlDRKSKv6kDqnw4U\n" + "wPdpOMXziC/AMj3Z/lUVX1G7WSHCAWKf1zNS1eLvqr+boEjXuBOitnZ/bDzPHrTOZz0Dew0uowxf\n" + "/+sG+NCK3eQJVxqcaJ/vEHKIVd2M+5qL71yJQ+87X6oV3eaYvt3zWZYD6z5vYTcrtij2VZ9Zmni/\n" + "UAaHqn9JdsBWLUEpVviYnhimNVvYFZeCXg/IdTQ+x4IRdiXNv5hEewIDAQABAoIBAQDl8Axy9XfW\n" + "BLmkzkEiqoSwF0PsmVrPzH9KsnwLGH+QZlvjWd8SWYGN7u1507HvhF5N3drJoVU3O14nDY4TFQAa\n" + "LlJ9VM35AApXaLyY1ERrN7u9ALKd2LUwYhM7Km539O4yUFYikE2nIPscEsA5ltpxOgUGCY7b7ez5\n" + "NtD6nL1ZKauw7aNXmVAvmJTcuPxWmoktF3gDJKK2wxZuNGcJE0uFQEG4Z3BrWP7yoNuSK3dii2jm\n" + "lpPHr0O/KnPQtzI3eguhe0TwUem/eYSdyzMyVx/YpwkzwtYL3sR5k0o9rKQLtvLzfAqdBxBurciz\n" + "aaA/L0HIgAmOit1GJA2saMxTVPNhAoGBAPfgv1oeZxgxmotiCcMXFEQEWflzhWYTsXrhUIuz5jFu\n" + "a39GLS99ZEErhLdrwj8rDDViRVJ5skOp9zFvlYAHs0xh92ji1E7V/ysnKBfsMrPkk5KSKPrnjndM\n" + "oPdevWnVkgJ5jxFuNgxkOLMuG9i53B4yMvDTCRiIPMQ++N2iLDaRAoGBAO9v//mU8eVkQaoANf0Z\n" + "oMjW8CN4xwWA2cSEIHkd9AfFkftuv8oyLDCG3ZAf0vrhrrtkrfa7ef+AUb69DNggq4mHQAYBp7L+\n" + "k5DKzJrKuO0r+R0YbY9pZD1+/g9dVt91d6LQNepUE/yY2PP5CNoFmjedpLHMOPFdVgqDzDFxU8hL\n" + "AoGBANDrr7xAJbqBjHVwIzQ4To9pb4BNeqDndk5Qe7fT3+/H1njGaC0/rXE0Qb7q5ySgnsCb3DvA\n" + "cJyRM9SJ7OKlGt0FMSdJD5KG0XPIpAVNwgpXXH5MDJg09KHeh0kXo+QA6viFBi21y340NonnEfdf\n" + "54PX4ZGS/Xac1UK+pLkBB+zRAoGAf0AY3H3qKS2lMEI4bzEFoHeK3G895pDaK3TFBVmD7fV0Zhov\n" + "17fegFPMwOII8MisYm9ZfT2Z0s5Ro3s5rkt+nvLAdfC/PYPKzTLalpGSwomSNYJcB9HNMlmhkGzc\n" + "1JnLYT4iyUyx6pcZBmCd8bD0iwY/FzcgNDaUmbX9+XDvRA0CgYEAkE7pIPlE71qvfJQgoA9em0gI\n" + "LAuE4Pu13aKiJnfft7hIjbK+5kyb3TysZvoyDnb3HOKvInK7vXbKuU4ISgxB2bB3HcYzQMGsz1qJ\n" + "2gG0N5hvJpzwwhbhXqFKA4zaaSrw622wDniAK5MlIE0tIAKKP4yxNGjoD2QYjhBGuhvkWKY=\n" + "-----END RSA PRIVATE KEY-----"; #ifdef WIN32 - unsigned char *out; - RSA *rsa; + unsigned char* out; + RSA* rsa; - BIO *bmem = BIO_new_mem_buf(super_secret_key, -1); - rsa = PEM_read_bio_RSAPrivateKey(bmem, NULL, NULL, NULL); - BIO_free(bmem); + BIO* bmem = BIO_new_mem_buf(super_secret_key, -1); + rsa = PEM_read_bio_RSAPrivateKey(bmem, NULL, NULL, NULL); + BIO_free(bmem); - out = malloc(RSA_size(rsa)); - switch (mode) { - case RSA_MODE_AUTH: - *outlen = RSA_private_encrypt(inlen, input, out, rsa, - RSA_PKCS1_PADDING); - break; - case RSA_MODE_KEY: - *outlen = RSA_private_decrypt(inlen, input, out, rsa, - RSA_PKCS1_OAEP_PADDING); - break; - } + out = malloc(RSA_size(rsa)); + switch(mode) { + case RSA_MODE_AUTH: + *outlen = RSA_private_encrypt(inlen, input, out, rsa, RSA_PKCS1_PADDING); + break; + case RSA_MODE_KEY: + *outlen = RSA_private_decrypt(inlen, input, out, rsa, RSA_PKCS1_OAEP_PADDING); + break; + } - RSA_free(rsa); + RSA_free(rsa); - return (char*) out; + return (char*)out; #else - mbedtls_pk_context pkctx; - mbedtls_rsa_context *trsa; - int ret; - size_t rsa_len; - size_t olen; - - /* + mbedtls_pk_context pkctx; + mbedtls_rsa_context* trsa; + int ret; + size_t rsa_len; + size_t olen; + + /* we should do entropy initialization & pass a rng function but this consumes a ton of stack and there is no security concern here. Anyway, mbedtls takes a lot of stack, unfortunately ... */ - mbedtls_pk_init(&pkctx); - ret = mbedtls_pk_parse_key(&pkctx, (unsigned char *)super_secret_key, - sizeof(super_secret_key), NULL, 0, raop_mbedtls_rng, NULL); - if (ret != 0 || !mbedtls_pk_can_do(&pkctx, MBEDTLS_PK_RSA)) { - LOG_ERROR("unable to parse RAOP private RSA key (%d)", ret); - mbedtls_pk_free(&pkctx); - return NULL; - } + mbedtls_pk_init(&pkctx); + ret = mbedtls_pk_parse_key(&pkctx, (unsigned char*)super_secret_key, sizeof(super_secret_key), NULL, 0, raop_mbedtls_rng, NULL); + if(ret != 0 || !mbedtls_pk_can_do(&pkctx, MBEDTLS_PK_RSA)) { + LOG_ERROR("unable to parse RAOP private RSA key (%d)", ret); + mbedtls_pk_free(&pkctx); + return NULL; + } - uint8_t *outbuf = NULL; - trsa = mbedtls_pk_rsa(pkctx); - rsa_len = mbedtls_rsa_get_len(trsa); + uint8_t* outbuf = NULL; + trsa = mbedtls_pk_rsa(pkctx); + rsa_len = mbedtls_rsa_get_len(trsa); - switch (mode) { - case RSA_MODE_AUTH: - mbedtls_rsa_set_padding(trsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); - outbuf = malloc(rsa_len); - if (!outbuf) break; - ret = mbedtls_rsa_pkcs1_sign(trsa, raop_mbedtls_rng, NULL, MBEDTLS_MD_NONE, - (unsigned int) inlen, input, outbuf); - if (ret != 0) { - LOG_ERROR("RSA auth sign failed (%d)", ret); - free(outbuf); - outbuf = NULL; - break; - } - *outlen = (int) rsa_len; - break; - case RSA_MODE_KEY: - mbedtls_rsa_set_padding(trsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); - outbuf = malloc(rsa_len); - if (!outbuf) break; - ret = mbedtls_rsa_pkcs1_decrypt(trsa, raop_mbedtls_rng, NULL, &olen, input, outbuf, rsa_len); - if (ret != 0) { - LOG_ERROR("RSA key decrypt failed (%d)", ret); - free(outbuf); - outbuf = NULL; - break; - } - *outlen = (int) olen; - break; - } + switch(mode) { + case RSA_MODE_AUTH: + mbedtls_rsa_set_padding(trsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); + outbuf = malloc(rsa_len); + if(!outbuf) break; + ret = mbedtls_rsa_pkcs1_sign(trsa, raop_mbedtls_rng, NULL, MBEDTLS_MD_NONE, (unsigned int)inlen, input, outbuf); + if(ret != 0) { + LOG_ERROR("RSA auth sign failed (%d)", ret); + free(outbuf); + outbuf = NULL; + break; + } + *outlen = (int)rsa_len; + break; + case RSA_MODE_KEY: + mbedtls_rsa_set_padding(trsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); + outbuf = malloc(rsa_len); + if(!outbuf) break; + ret = mbedtls_rsa_pkcs1_decrypt(trsa, raop_mbedtls_rng, NULL, &olen, input, outbuf, rsa_len); + if(ret != 0) { + LOG_ERROR("RSA key decrypt failed (%d)", ret); + free(outbuf); + outbuf = NULL; + break; + } + *outlen = (int)olen; + break; + } - mbedtls_pk_free(&pkctx); + mbedtls_pk_free(&pkctx); - return (char*) outbuf; + return (char*)outbuf; #endif } #define DECODE_ERROR 0xffffffff -const static char base64_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const static char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /*----------------------------------------------------------------------------*/ -static int base64_pad(char *src, char **padded) -{ - int n; +static int base64_pad(char* src, char** padded) { + int n; - n = strlen(src) + strlen(src) % 4; - *padded = malloc(n + 1); - memset(*padded, '=', n); - memcpy(*padded, src, strlen(src)); - (*padded)[n] = '\0'; + n = strlen(src) + strlen(src) % 4; + *padded = malloc(n + 1); + memset(*padded, '=', n); + memcpy(*padded, src, strlen(src)); + (*padded)[n] = '\0'; - return strlen(*padded); + return strlen(*padded); } /*----------------------------------------------------------------------------*/ -static int pos(char c) -{ - const char *p; - for (p = base64_chars; *p; p++) - if (*p == c) - return p - base64_chars; - return -1; +static int pos(char c) { + const char* p; + for(p = base64_chars; *p; p++) + if(*p == c) return p - base64_chars; + return -1; } /*----------------------------------------------------------------------------*/ -static int base64_encode(const void *data, int size, char **str) -{ - char *s, *p; - int i; - int c; - const unsigned char *q; +static int base64_encode(const void* data, int size, char** str) { + char *s, *p; + int i; + int c; + const unsigned char* q; - p = s = (char *) malloc(size * 4 / 3 + 4); - if (p == NULL) return -1; - q = (const unsigned char *) data; - i = 0; - for (i = 0; i < size;) { - c = q[i++]; - c *= 256; - if (i < size) c += q[i]; - i++; - c *= 256; - if (i < size) c += q[i]; - i++; - p[0] = base64_chars[(c & 0x00fc0000) >> 18]; - p[1] = base64_chars[(c & 0x0003f000) >> 12]; - p[2] = base64_chars[(c & 0x00000fc0) >> 6]; - p[3] = base64_chars[(c & 0x0000003f) >> 0]; - if (i > size) p[3] = '='; - if (i > size + 1) p[2] = '='; - p += 4; - } - *p = 0; - *str = s; - return strlen(s); + p = s = (char*)malloc(size * 4 / 3 + 4); + if(p == NULL) return -1; + q = (const unsigned char*)data; + i = 0; + for(i = 0; i < size;) { + c = q[i++]; + c *= 256; + if(i < size) c += q[i]; + i++; + c *= 256; + if(i < size) c += q[i]; + i++; + p[0] = base64_chars[(c & 0x00fc0000) >> 18]; + p[1] = base64_chars[(c & 0x0003f000) >> 12]; + p[2] = base64_chars[(c & 0x00000fc0) >> 6]; + p[3] = base64_chars[(c & 0x0000003f) >> 0]; + if(i > size) p[3] = '='; + if(i > size + 1) p[2] = '='; + p += 4; + } + *p = 0; + *str = s; + return strlen(s); } /*----------------------------------------------------------------------------*/ -static unsigned int token_decode(const char *token) -{ - int i; - unsigned int val = 0; - int marker = 0; - if (strlen(token) < 4) - return DECODE_ERROR; - for (i = 0; i < 4; i++) { - val *= 64; - if (token[i] == '=') - marker++; - else if (marker > 0) - return DECODE_ERROR; - else - val += pos(token[i]); - } - if (marker > 2) - return DECODE_ERROR; - return (marker << 24) | val; +static unsigned int token_decode(const char* token) { + int i; + unsigned int val = 0; + int marker = 0; + if(strlen(token) < 4) return DECODE_ERROR; + for(i = 0; i < 4; i++) { + val *= 64; + if(token[i] == '=') + marker++; + else if(marker > 0) + return DECODE_ERROR; + else + val += pos(token[i]); + } + if(marker > 2) return DECODE_ERROR; + return (marker << 24) | val; } /*----------------------------------------------------------------------------*/ -static int base64_decode(const char *str, void *data) -{ - const char *p; - unsigned char *q; +static int base64_decode(const char* str, void* data) { + const char* p; + unsigned char* q; - q = data; - for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) { - unsigned int val = token_decode(p); - unsigned int marker = (val >> 24) & 0xff; - if (val == DECODE_ERROR) - return -1; - *q++ = (val >> 16) & 0xff; - if (marker < 2) - *q++ = (val >> 8) & 0xff; - if (marker < 1) - *q++ = val & 0xff; - } - return q - (unsigned char *) data; + q = data; + for(p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) { + unsigned int val = token_decode(p); + unsigned int marker = (val >> 24) & 0xff; + if(val == DECODE_ERROR) return -1; + *q++ = (val >> 16) & 0xff; + if(marker < 2) *q++ = (val >> 8) & 0xff; + if(marker < 1) *q++ = val & 0xff; + } + return q - (unsigned char*)data; } /*----------------------------------------------------------------------------*/ -static void on_dmap_string(void *ctx, const char *code, const char *name, const char *buf, size_t len) { - struct metadata_s *metadata = (struct metadata_s *) ctx; +static void on_dmap_string(void* ctx, const char* code, const char* name, const char* buf, size_t len) { + struct metadata_s* metadata = (struct metadata_s*)ctx; // to gain space, most of the code have been removed from dmap_parser.c (define DMAP_FULL - if (!strcasecmp(code, "asar")) metadata->artist = strndup(buf, len); - else if (!strcasecmp(code, "asal")) metadata->album = strndup(buf, len); - else if (!strcasecmp(code, "minm")) metadata->title = strndup(buf, len); + if(!strcasecmp(code, "asar")) + metadata->artist = strndup(buf, len); + else if(!strcasecmp(code, "asal")) + metadata->album = strndup(buf, len); + else if(!strcasecmp(code, "minm")) + metadata->title = strndup(buf, len); } diff --git a/components/raop/raop.h b/components/raop/raop.h index 07042b06..ef22669d 100644 --- a/components/raop/raop.h +++ b/components/raop/raop.h @@ -11,9 +11,7 @@ #include "platform.h" #include "raop_sink.h" -struct raop_ctx_s* raop_create(uint32_t host, char *name, unsigned char mac[6], int latency, - raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb); -void raop_delete(struct raop_ctx_s *ctx); -void raop_abort(struct raop_ctx_s *ctx); -bool raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param); - +struct raop_ctx_s* raop_create(uint32_t host, char* name, unsigned char mac[6], int latency, raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb); +void raop_delete(struct raop_ctx_s* ctx); +void raop_abort(struct raop_ctx_s* ctx); +bool raop_cmd(struct raop_ctx_s* ctx, raop_event_t event, void* param); diff --git a/components/raop/raop_sink.c b/components/raop/raop_sink.c index b0ba42ee..2069698f 100644 --- a/components/raop/raop_sink.c +++ b/components/raop/raop_sink.c @@ -18,184 +18,183 @@ #include "network_services.h" #ifndef CONFIG_AIRPLAY_NAME -#define CONFIG_AIRPLAY_NAME "ESP32-AirPlay" +#define CONFIG_AIRPLAY_NAME "ESP32-AirPlay" #endif static EXT_RAM_ATTR struct raop_cb_s { - raop_cmd_vcb_t cmd; - raop_data_cb_t data; + raop_cmd_vcb_t cmd; + raop_data_cb_t data; } raop_cbs; -log_level raop_loglevel = lINFO; -log_level util_loglevel; +log_level raop_loglevel = lINFO; +log_level util_loglevel; -static log_level *loglevel = &raop_loglevel; -static struct raop_ctx_s *raop; +static log_level* loglevel = &raop_loglevel; +static struct raop_ctx_s* raop; static raop_cmd_vcb_t cmd_handler_chain; static void raop_volume_up(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_VOLUME_UP, NULL); - LOG_INFO("AirPlay volume up"); + if(!pressed) return; + raop_cmd(raop, RAOP_VOLUME_UP, NULL); + LOG_INFO("AirPlay volume up"); } static void raop_volume_down(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_VOLUME_DOWN, NULL); - LOG_INFO("AirPlay volume down"); + if(!pressed) return; + raop_cmd(raop, RAOP_VOLUME_DOWN, NULL); + LOG_INFO("AirPlay volume down"); } static void raop_toggle(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_TOGGLE, NULL); - LOG_INFO("AirPlay play/pause"); + if(!pressed) return; + raop_cmd(raop, RAOP_TOGGLE, NULL); + LOG_INFO("AirPlay play/pause"); } static void raop_pause(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_PAUSE, NULL); - LOG_INFO("AirPlay pause"); + if(!pressed) return; + raop_cmd(raop, RAOP_PAUSE, NULL); + LOG_INFO("AirPlay pause"); } static void raop_play(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_PLAY, NULL); - LOG_INFO("AirPlay play"); + if(!pressed) return; + raop_cmd(raop, RAOP_PLAY, NULL); + LOG_INFO("AirPlay play"); } static void raop_stop(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_STOP, NULL); - LOG_INFO("AirPlay stop"); + if(!pressed) return; + raop_cmd(raop, RAOP_STOP, NULL); + LOG_INFO("AirPlay stop"); } static void raop_prev(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_PREV, NULL); - LOG_INFO("AirPlay previous"); + if(!pressed) return; + raop_cmd(raop, RAOP_PREV, NULL); + LOG_INFO("AirPlay previous"); } static void raop_next(bool pressed) { - if (!pressed) return; - raop_cmd(raop, RAOP_NEXT, NULL); - LOG_INFO("AirPlay next"); + if(!pressed) return; + raop_cmd(raop, RAOP_NEXT, NULL); + LOG_INFO("AirPlay next"); } const static actrls_t controls = { - NULL, // power - raop_volume_up, raop_volume_down, // volume up, volume down - raop_toggle, raop_play, // toggle, play - raop_pause, raop_stop, // pause, stop - NULL, NULL, // rew, fwd - raop_prev, raop_next, // prev, next - NULL, NULL, NULL, NULL, // left, right, up, down - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 - raop_volume_down, raop_volume_up, raop_toggle// knob left, knob_right, knob push + NULL, // power + raop_volume_up, raop_volume_down, // volume up, volume down + raop_toggle, raop_play, // toggle, play + raop_pause, raop_stop, // pause, stop + NULL, NULL, // rew, fwd + raop_prev, raop_next, // prev, next + NULL, NULL, NULL, NULL, // left, right, up, down + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 + raop_volume_down, raop_volume_up, raop_toggle // knob left, knob_right, knob push }; /**************************************************************************************** * Command handler */ static bool cmd_handler(raop_event_t event, ...) { - va_list args; - - va_start(args, event); - - // handle audio event and stop if forbidden - if (!cmd_handler_chain(event, args)) { - va_end(args); - return false; - } + va_list args; - // now handle events for display - switch(event) { - case RAOP_SETUP: - actrls_set(controls, false, NULL, actrls_ir_action); - displayer_control(DISPLAYER_ACTIVATE, "AIRPLAY", true); + va_start(args, event); + + // handle audio event and stop if forbidden + if(!cmd_handler_chain(event, args)) { + va_end(args); + return false; + } + + // now handle events for display + switch(event) { + case RAOP_SETUP: + actrls_set(controls, false, NULL, actrls_ir_action); + displayer_control(DISPLAYER_ACTIVATE, "AIRPLAY", true); displayer_artwork(NULL); - break; - case RAOP_PLAY: - displayer_control(DISPLAYER_TIMER_RUN); - break; - case RAOP_FLUSH: - displayer_control(DISPLAYER_TIMER_PAUSE); - break; + break; + case RAOP_PLAY: + displayer_control(DISPLAYER_TIMER_RUN); + break; + case RAOP_FLUSH: + displayer_control(DISPLAYER_TIMER_PAUSE); + break; case RAOP_STALLED: raop_abort(raop); actrls_unset(); displayer_control(DISPLAYER_SHUTDOWN); break; - case RAOP_STOP: - actrls_unset(); - displayer_control(DISPLAYER_SUSPEND); - break; - case RAOP_METADATA: { - char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); - displayer_metadata(artist, album, title); - break; - } - case RAOP_ARTWORK: { - uint8_t *data = va_arg(args, uint8_t*); - displayer_artwork(data); - break; - } - case RAOP_PROGRESS: { - int elapsed = va_arg(args, int), duration = va_arg(args, int); - displayer_timer(DISPLAYER_ELAPSED, elapsed, duration); - break; - } - default: - break; - } - - va_end(args); - - return true; + case RAOP_STOP: + actrls_unset(); + displayer_control(DISPLAYER_SUSPEND); + break; + case RAOP_METADATA: { + char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*); + displayer_metadata(artist, album, title); + break; + } + case RAOP_ARTWORK: { + uint8_t* data = va_arg(args, uint8_t*); + displayer_artwork(data); + break; + } + case RAOP_PROGRESS: { + int elapsed = va_arg(args, int), duration = va_arg(args, int); + displayer_timer(DISPLAYER_ELAPSED, elapsed, duration); + break; + } + default: + break; + } + + va_end(args); + + return true; } /**************************************************************************************** * Airplay sink de-initialization */ -void raop_sink_deinit(void) { - raop_delete(raop); -} +void raop_sink_deinit(void) { raop_delete(raop); } /**************************************************************************************** * Airplay sink startup */ static void raop_sink_start(nm_state_t state_id, int sub_state) { - esp_netif_t* netif; - esp_netif_ip_info_t ipInfo = { }; - uint8_t mac[6]; - char* sink_name = strlen(platform->names.airplay)>0?platform->names.airplay:platform->names.device; - + esp_netif_t* netif; + esp_netif_ip_info_t ipInfo = {}; + uint8_t mac[6]; + char* sink_name = strlen(platform->names.airplay) > 0 ? platform->names.airplay : platform->names.device; netif = network_get_active_interface(); - esp_netif_get_ip_info(netif, &ipInfo); - esp_netif_get_mac(netif, mac); - cmd_handler_chain = raop_cbs.cmd; + esp_netif_get_ip_info(netif, &ipInfo); + esp_netif_get_mac(netif, mac); + cmd_handler_chain = raop_cbs.cmd; - LOG_INFO( "starting Airplay for ip %s with servicename %s", inet_ntoa(ipInfo.ip.addr), sink_name); - raop = raop_create(ipInfo.ip.addr, sink_name, mac, 0, cmd_handler, raop_cbs.data); + LOG_INFO("starting Airplay for ip %s with servicename %s", inet_ntoa(ipInfo.ip.addr), sink_name); + raop = raop_create(ipInfo.ip.addr, sink_name, mac, 0, cmd_handler, raop_cbs.data); } /**************************************************************************************** * Airplay sink initialization */ void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) { - raop_cbs.cmd = cmd_cb; - raop_cbs.data = data_cb; + raop_cbs.cmd = cmd_cb; + raop_cbs.data = data_cb; - network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_CONNECTED_STATE, "raop_sink_start", raop_sink_start); - network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_CONNECTED_STATE, "raop_sink_start", raop_sink_start); + network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_CONNECTED_STATE, "raop_sink_start", raop_sink_start); + network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_CONNECTED_STATE, "raop_sink_start", raop_sink_start); } /**************************************************************************************** * Airplay forced disconnection */ void raop_disconnect(void) { - LOG_INFO("forced disconnection"); - // in case we can't communicate with AirPlay controller, abort session - if (!raop_cmd(raop, RAOP_STOP, NULL)) cmd_handler(RAOP_STALLED); - else displayer_control(DISPLAYER_SHUTDOWN); + LOG_INFO("forced disconnection"); + // in case we can't communicate with AirPlay controller, abort session + if(!raop_cmd(raop, RAOP_STOP, NULL)) + cmd_handler(RAOP_STALLED); + else + displayer_control(DISPLAYER_SHUTDOWN); } diff --git a/components/raop/raop_sink.h b/components/raop/raop_sink.h index 99558fa9..b7bcd90a 100644 --- a/components/raop/raop_sink.h +++ b/components/raop/raop_sink.h @@ -12,15 +12,34 @@ #include #include -#define RAOP_SAMPLE_RATE 44100 +#define RAOP_SAMPLE_RATE 44100 -typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_METADATA, RAOP_ARTWORK, RAOP_PROGRESS, RAOP_PAUSE, RAOP_STOP, RAOP_STALLED, - RAOP_VOLUME, RAOP_TIMING, RAOP_PREV, RAOP_NEXT, RAOP_REW, RAOP_FWD, - RAOP_VOLUME_UP, RAOP_VOLUME_DOWN, RAOP_RESUME, RAOP_TOGGLE } raop_event_t ; +typedef enum { + RAOP_SETUP, + RAOP_STREAM, + RAOP_PLAY, + RAOP_FLUSH, + RAOP_METADATA, + RAOP_ARTWORK, + RAOP_PROGRESS, + RAOP_PAUSE, + RAOP_STOP, + RAOP_STALLED, + RAOP_VOLUME, + RAOP_TIMING, + RAOP_PREV, + RAOP_NEXT, + RAOP_REW, + RAOP_FWD, + RAOP_VOLUME_UP, + RAOP_VOLUME_DOWN, + RAOP_RESUME, + RAOP_TOGGLE +} raop_event_t; typedef bool (*raop_cmd_cb_t)(raop_event_t event, ...); typedef bool (*raop_cmd_vcb_t)(raop_event_t event, va_list args); -typedef void (*raop_data_cb_t)(const u8_t *data, size_t len, u32_t playtime); +typedef void (*raop_data_cb_t)(const u8_t* data, size_t len, u32_t playtime); /** * @brief init sink mode (need to be provided) diff --git a/components/raop/rtp.c b/components/raop/rtp.c index 2f0f8b05..075e5fe8 100644 --- a/components/raop/rtp.c +++ b/components/raop/rtp.c @@ -59,778 +59,764 @@ #endif #define NTP2MS(ntp) ((((ntp) >> 10) * 1000L) >> 22) -#define MS2NTP(ms) (((((u64_t) (ms)) << 22) / 1000) << 10) +#define MS2NTP(ms) (((((u64_t)(ms)) << 22) / 1000) << 10) #define NTP2TS(ntp, rate) ((((ntp) >> 16) * (rate)) >> 16) -#define TS2NTP(ts, rate) (((((u64_t) (ts)) << 16) / (rate)) << 16) -#define MS2TS(ms, rate) ((((u64_t) (ms)) * (rate)) / 1000) -#define TS2MS(ts, rate) NTP2MS(TS2NTP(ts,rate)) +#define TS2NTP(ts, rate) (((((u64_t)(ts)) << 16) / (rate)) << 16) +#define MS2TS(ms, rate) ((((u64_t)(ms)) * (rate)) / 1000) +#define TS2MS(ts, rate) NTP2MS(TS2NTP(ts, rate)) -extern log_level raop_loglevel; -static log_level *loglevel = &raop_loglevel; +extern log_level raop_loglevel; +static log_level* loglevel = &raop_loglevel; //#define __RTP_STORE // default buffer size -#define BUFFER_FRAMES_MAX ((RAOP_SAMPLE_RATE * 10) / 352 ) -#define BUFFER_FRAMES_MIN ( (150 * RAOP_SAMPLE_RATE * 2) / (352 * 100) ) -#define MAX_PACKET 1408 -#define MIN_LATENCY 11025 -#define MAX_LATENCY ( (120 * RAOP_SAMPLE_RATE * 2) / 100 ) +#define BUFFER_FRAMES_MAX ((RAOP_SAMPLE_RATE * 10) / 352) +#define BUFFER_FRAMES_MIN ((150 * RAOP_SAMPLE_RATE * 2) / (352 * 100)) +#define MAX_PACKET 1408 +#define MIN_LATENCY 11025 +#define MAX_LATENCY ((120 * RAOP_SAMPLE_RATE * 2) / 100) -#define RTP_STACK_SIZE (4*1024) +#define RTP_STACK_SIZE (4 * 1024) -#define RTP_SYNC (0x01) -#define NTP_SYNC (0x02) +#define RTP_SYNC (0x01) +#define NTP_SYNC (0x02) -#define RESEND_TO 250 +#define RESEND_TO 250 enum { DATA = 0, CONTROL, TIMING }; -static const u8_t silence_frame[MAX_PACKET] = { 0 }; +static const u8_t silence_frame[MAX_PACKET] = {0}; uint32_t buffer_frames = ((150 * RAOP_SAMPLE_RATE * 2) / (352 * 100)); typedef u16_t seq_t; -typedef struct __attribute__((__packed__)) audio_buffer_entry { // decoded audio packets - u32_t rtptime, last_resend; - s16_t *data; - u16_t len; +typedef struct __attribute__((__packed__)) audio_buffer_entry { // decoded audio packets + u32_t rtptime, last_resend; + s16_t* data; + u16_t len; u8_t ready; u8_t allocated; } abuf_t; typedef struct rtp_s { #ifdef __RTP_STORE - FILE *rtpIN, *rtpOUT; + FILE *rtpIN, *rtpOUT; #endif - bool running; - unsigned char aesiv[16]; + bool running; + unsigned char aesiv[16]; #ifdef WIN32 - AES_KEY aes; + AES_KEY aes; #else - mbedtls_aes_context aes; + mbedtls_aes_context aes; #endif - bool decrypt; - u8_t *decrypt_buf; - u32_t frame_size, frame_duration; - u32_t in_frames, out_frames; - struct in_addr host; - struct sockaddr_in rtp_host; - struct { - unsigned short rport, lport; - int sock; - } rtp_sockets[3]; // data, control, timing - struct timing_s { - u64_t local, remote; - } timing; - struct { - u32_t rtp, time; - u8_t status; - } synchro; - struct { - u32_t time; - seq_t seqno; - u32_t rtptime; - } record; - int latency; // rtp hold depth in samples - u32_t resent_req, resent_rec; // total resent + recovered frames - u32_t silent_frames; // total silence frames - u32_t discarded; - abuf_t audio_buffer[BUFFER_FRAMES_MAX]; - seq_t ab_read, ab_write; - pthread_mutex_t ab_mutex; + bool decrypt; + u8_t* decrypt_buf; + u32_t frame_size, frame_duration; + u32_t in_frames, out_frames; + struct in_addr host; + struct sockaddr_in rtp_host; + struct { + unsigned short rport, lport; + int sock; + } rtp_sockets[3]; // data, control, timing + struct timing_s { + u64_t local, remote; + } timing; + struct { + u32_t rtp, time; + u8_t status; + } synchro; + struct { + u32_t time; + seq_t seqno; + u32_t rtptime; + } record; + int latency; // rtp hold depth in samples + u32_t resent_req, resent_rec; // total resent + recovered frames + u32_t silent_frames; // total silence frames + u32_t discarded; + abuf_t audio_buffer[BUFFER_FRAMES_MAX]; + seq_t ab_read, ab_write; + pthread_mutex_t ab_mutex; #ifdef WIN32 - pthread_t thread; + pthread_t thread; #else - TaskHandle_t thread, joiner; - StaticTask_t *xTaskBuffer; - StackType_t xStack[RTP_STACK_SIZE] __attribute__ ((aligned (4))); + TaskHandle_t thread, joiner; + StaticTask_t* xTaskBuffer; + StackType_t xStack[RTP_STACK_SIZE] __attribute__((aligned(4))); #endif - struct alac_codec_s *alac_codec; - int flush_seqno; - bool playing; + struct alac_codec_s* alac_codec; + int flush_seqno; + bool playing; int stalled; - raop_data_cb_t data_cb; - raop_cmd_cb_t cmd_cb; + raop_data_cb_t data_cb; + raop_cmd_cb_t cmd_cb; } rtp_t; - #define BUFIDX(seqno) ((seq_t)(seqno) % buffer_frames) -static void buffer_alloc(abuf_t *audio_buffer, int size, uint8_t *buf, size_t buf_size); -static void buffer_release(abuf_t *audio_buffer); -static void buffer_reset(abuf_t *audio_buffer); -static void buffer_push_packet(rtp_t *ctx); -static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last); -static bool rtp_request_timing(rtp_t *ctx); -static int seq_order(seq_t a, seq_t b); +static void buffer_alloc(abuf_t* audio_buffer, int size, uint8_t* buf, size_t buf_size); +static void buffer_release(abuf_t* audio_buffer); +static void buffer_reset(abuf_t* audio_buffer); +static void buffer_push_packet(rtp_t* ctx); +static bool rtp_request_resend(rtp_t* ctx, seq_t first, seq_t last); +static bool rtp_request_timing(rtp_t* ctx); +static int seq_order(seq_t a, seq_t b); #ifdef WIN32 -static void *rtp_thread_func(void *arg); +static void* rtp_thread_func(void* arg); #else -static void rtp_thread_func(void *arg); -#endif +static void rtp_thread_func(void* arg); +#endif /*---------------------------------------------------------------------------*/ static struct alac_codec_s* alac_init(int fmtp[32]) { - struct alac_codec_s *alac; - unsigned sample_rate, block_size; - unsigned char sample_size, channels; - struct { - uint32_t frameLength; - uint8_t compatibleVersion; - uint8_t bitDepth; - uint8_t pb; - uint8_t mb; - uint8_t kb; - uint8_t numChannels; - uint16_t maxRun; - uint32_t maxFrameBytes; - uint32_t avgBitRate; - uint32_t sampleRate; - } config; + struct alac_codec_s* alac; + unsigned sample_rate, block_size; + unsigned char sample_size, channels; + struct { + uint32_t frameLength; + uint8_t compatibleVersion; + uint8_t bitDepth; + uint8_t pb; + uint8_t mb; + uint8_t kb; + uint8_t numChannels; + uint16_t maxRun; + uint32_t maxFrameBytes; + uint32_t avgBitRate; + uint32_t sampleRate; + } config; - config.frameLength = htonl(fmtp[1]); - config.compatibleVersion = fmtp[2]; - config.bitDepth = fmtp[3]; - config.pb = fmtp[4]; - config.mb = fmtp[5]; - config.kb = fmtp[6]; - config.numChannels = fmtp[7]; - config.maxRun = htons(fmtp[8]); - config.maxFrameBytes = htonl(fmtp[9]); - config.avgBitRate = htonl(fmtp[10]); - config.sampleRate = htonl(fmtp[11]); + config.frameLength = htonl(fmtp[1]); + config.compatibleVersion = fmtp[2]; + config.bitDepth = fmtp[3]; + config.pb = fmtp[4]; + config.mb = fmtp[5]; + config.kb = fmtp[6]; + config.numChannels = fmtp[7]; + config.maxRun = htons(fmtp[8]); + config.maxFrameBytes = htonl(fmtp[9]); + config.avgBitRate = htonl(fmtp[10]); + config.sampleRate = htonl(fmtp[11]); - alac = alac_create_decoder(sizeof(config), (unsigned char*) &config, &sample_size, &sample_rate, &channels, &block_size); - if (!alac) { - LOG_ERROR("cannot create alac codec", NULL); - return NULL; - } + alac = alac_create_decoder(sizeof(config), (unsigned char*)&config, &sample_size, &sample_rate, &channels, &block_size); + if(!alac) { + LOG_ERROR("cannot create alac codec", NULL); + return NULL; + } - return alac; + return alac; } /*---------------------------------------------------------------------------*/ -rtp_resp_t rtp_init(struct in_addr host, int latency, char *aeskey, char *aesiv, char *fmtpstr, - short unsigned pCtrlPort, short unsigned pTimingPort, - uint8_t *buffer, size_t size, - raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) -{ - int i = 0; - char *arg; - int fmtp[32]; - bool rc = true; - rtp_t *ctx = calloc(1, sizeof(rtp_t)); - rtp_resp_t resp = { 0, 0, 0, NULL }; +rtp_resp_t rtp_init(struct in_addr host, int latency, char* aeskey, char* aesiv, char* fmtpstr, short unsigned pCtrlPort, short unsigned pTimingPort, + uint8_t* buffer, size_t size, raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) { + int i = 0; + char* arg; + int fmtp[32]; + bool rc = true; + rtp_t* ctx = calloc(1, sizeof(rtp_t)); + rtp_resp_t resp = {0, 0, 0, NULL}; - if (!ctx) return resp; - - ctx->host = host; - ctx->decrypt = false; - ctx->cmd_cb = cmd_cb; - ctx->data_cb = data_cb; - ctx->rtp_host.sin_family = AF_INET; - ctx->rtp_host.sin_addr.s_addr = INADDR_ANY; - pthread_mutex_init(&ctx->ab_mutex, 0); - ctx->flush_seqno = -1; - ctx->latency = latency; - ctx->ab_read = ctx->ab_write; + if(!ctx) return resp; + + ctx->host = host; + ctx->decrypt = false; + ctx->cmd_cb = cmd_cb; + ctx->data_cb = data_cb; + ctx->rtp_host.sin_family = AF_INET; + ctx->rtp_host.sin_addr.s_addr = INADDR_ANY; + pthread_mutex_init(&ctx->ab_mutex, 0); + ctx->flush_seqno = -1; + ctx->latency = latency; + ctx->ab_read = ctx->ab_write; #ifdef __RTP_STORE - ctx->rtpIN = fopen("airplay.rtpin", "wb"); - ctx->rtpOUT = fopen("airplay.rtpout", "wb"); + ctx->rtpIN = fopen("airplay.rtpin", "wb"); + ctx->rtpOUT = fopen("airplay.rtpout", "wb"); #endif - ctx->rtp_sockets[CONTROL].rport = pCtrlPort; - ctx->rtp_sockets[TIMING].rport = pTimingPort; + ctx->rtp_sockets[CONTROL].rport = pCtrlPort; + ctx->rtp_sockets[TIMING].rport = pTimingPort; - if (aesiv && aeskey) { - memcpy(ctx->aesiv, aesiv, 16); + if(aesiv && aeskey) { + memcpy(ctx->aesiv, aesiv, 16); #ifdef WIN32 - AES_set_decrypt_key((unsigned char*) aeskey, 128, &ctx->aes); + AES_set_decrypt_key((unsigned char*)aeskey, 128, &ctx->aes); #else - memset(&ctx->aes, 0, sizeof(mbedtls_aes_context)); - mbedtls_aes_setkey_dec(&ctx->aes, (unsigned char*) aeskey, 128); + memset(&ctx->aes, 0, sizeof(mbedtls_aes_context)); + mbedtls_aes_setkey_dec(&ctx->aes, (unsigned char*)aeskey, 128); #endif - ctx->decrypt = true; - ctx->decrypt_buf = malloc(MAX_PACKET); - } + ctx->decrypt = true; + ctx->decrypt_buf = malloc(MAX_PACKET); + } - memset(fmtp, 0, sizeof(fmtp)); - while ((arg = strsep(&fmtpstr, " \t")) != NULL) fmtp[i++] = atoi(arg); + memset(fmtp, 0, sizeof(fmtp)); + while((arg = strsep(&fmtpstr, " \t")) != NULL) fmtp[i++] = atoi(arg); - ctx->frame_size = fmtp[1]; - ctx->frame_duration = (ctx->frame_size * 1000) / RAOP_SAMPLE_RATE; + ctx->frame_size = fmtp[1]; + ctx->frame_duration = (ctx->frame_size * 1000) / RAOP_SAMPLE_RATE; - // alac decoder - ctx->alac_codec = alac_init(fmtp); - rc &= ctx->alac_codec != NULL; + // alac decoder + ctx->alac_codec = alac_init(fmtp); + rc &= ctx->alac_codec != NULL; - buffer_alloc(ctx->audio_buffer, ctx->frame_size*4, buffer, size); + buffer_alloc(ctx->audio_buffer, ctx->frame_size * 4, buffer, size); - // create rtp ports - for (i = 0; i < 3; i++) { - ctx->rtp_sockets[i].sock = bind_socket(&ctx->rtp_sockets[i].lport, SOCK_DGRAM); - rc &= ctx->rtp_sockets[i].sock > 0; - } + // create rtp ports + for(i = 0; i < 3; i++) { + ctx->rtp_sockets[i].sock = bind_socket(&ctx->rtp_sockets[i].lport, SOCK_DGRAM); + rc &= ctx->rtp_sockets[i].sock > 0; + } - // create http port and start listening - resp.cport = ctx->rtp_sockets[CONTROL].lport; - resp.tport = ctx->rtp_sockets[TIMING].lport; - resp.aport = ctx->rtp_sockets[DATA].lport; - - ctx->running = true; + // create http port and start listening + resp.cport = ctx->rtp_sockets[CONTROL].lport; + resp.tport = ctx->rtp_sockets[TIMING].lport; + resp.aport = ctx->rtp_sockets[DATA].lport; + + ctx->running = true; #ifdef WIN32 - pthread_create(&ctx->thread, NULL, rtp_thread_func, (void *) ctx); + pthread_create(&ctx->thread, NULL, rtp_thread_func, (void*)ctx); #else - ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - ctx->thread = xTaskCreateStaticPinnedToCore( (TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx, - CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer, - CONFIG_PTHREAD_TASK_CORE_DEFAULT ); + ctx->xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + ctx->thread = xTaskCreateStaticPinnedToCore((TaskFunction_t)rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx, + CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer, CONFIG_PTHREAD_TASK_CORE_DEFAULT); #endif - - // cleanup everything if we failed - if (!rc) { - LOG_ERROR("[%p]: cannot start RTP", ctx); - rtp_end(ctx); - ctx = NULL; - } - - resp.ctx = ctx; - return resp; + + // cleanup everything if we failed + if(!rc) { + LOG_ERROR("[%p]: cannot start RTP", ctx); + rtp_end(ctx); + ctx = NULL; + } + + resp.ctx = ctx; + return resp; } /*---------------------------------------------------------------------------*/ -void rtp_end(rtp_t *ctx) -{ - int i; +void rtp_end(rtp_t* ctx) { + int i; - if (!ctx) return; + if(!ctx) return; - if (ctx->running) { -#if !defined WIN32 - ctx->joiner = xTaskGetCurrentTaskHandle(); + if(ctx->running) { +#if !defined WIN32 + ctx->joiner = xTaskGetCurrentTaskHandle(); #endif - ctx->running = false; + ctx->running = false; #ifdef WIN32 - pthread_join(ctx->thread, NULL); + pthread_join(ctx->thread, NULL); #else - ulTaskNotifyTake(pdFALSE, portMAX_DELAY); - vTaskDelete(ctx->thread); - SAFE_PTR_FREE(ctx->xTaskBuffer); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + vTaskDelete(ctx->thread); + SAFE_PTR_FREE(ctx->xTaskBuffer); #endif - } - - for (i = 0; i < 3; i++) closesocket(ctx->rtp_sockets[i].sock); + } - if (ctx->alac_codec) alac_delete_decoder(ctx->alac_codec); - if (ctx->decrypt_buf) free(ctx->decrypt_buf); - - pthread_mutex_destroy(&ctx->ab_mutex); - buffer_release(ctx->audio_buffer); - - free(ctx); + for(i = 0; i < 3; i++) closesocket(ctx->rtp_sockets[i].sock); + + if(ctx->alac_codec) alac_delete_decoder(ctx->alac_codec); + if(ctx->decrypt_buf) free(ctx->decrypt_buf); + + pthread_mutex_destroy(&ctx->ab_mutex); + buffer_release(ctx->audio_buffer); + + free(ctx); #ifdef __RTP_STORE - fclose(ctx->rtpIN); - fclose(ctx->rtpOUT); + fclose(ctx->rtpIN); + fclose(ctx->rtpOUT); #endif } /*---------------------------------------------------------------------------*/ -bool rtp_flush(rtp_t *ctx, unsigned short seqno, unsigned int rtptime, bool exit_locked) -{ - bool rc = true; - u32_t now = gettime_ms(); +bool rtp_flush(rtp_t* ctx, unsigned short seqno, unsigned int rtptime, bool exit_locked) { + bool rc = true; + u32_t now = gettime_ms(); - if (now < ctx->record.time + 250 || (ctx->record.seqno == seqno && ctx->record.rtptime == rtptime)) { - rc = false; - LOG_ERROR("[%p]: FLUSH ignored as same as RECORD (%hu - %u)", ctx, seqno, rtptime); - } else { - pthread_mutex_lock(&ctx->ab_mutex); - buffer_reset(ctx->audio_buffer); - ctx->playing = false; - ctx->flush_seqno = seqno; - if (!exit_locked) pthread_mutex_unlock(&ctx->ab_mutex); - } + if(now < ctx->record.time + 250 || (ctx->record.seqno == seqno && ctx->record.rtptime == rtptime)) { + rc = false; + LOG_ERROR("[%p]: FLUSH ignored as same as RECORD (%hu - %u)", ctx, seqno, rtptime); + } else { + pthread_mutex_lock(&ctx->ab_mutex); + buffer_reset(ctx->audio_buffer); + ctx->playing = false; + ctx->flush_seqno = seqno; + if(!exit_locked) pthread_mutex_unlock(&ctx->ab_mutex); + } - LOG_INFO("[%p]: flush %hu %u", ctx, seqno, rtptime); + LOG_INFO("[%p]: flush %hu %u", ctx, seqno, rtptime); - return rc; + return rc; } /*---------------------------------------------------------------------------*/ -void rtp_flush_release(rtp_t *ctx) { - pthread_mutex_unlock(&ctx->ab_mutex); -} - +void rtp_flush_release(rtp_t* ctx) { pthread_mutex_unlock(&ctx->ab_mutex); } /*---------------------------------------------------------------------------*/ -void rtp_record(rtp_t *ctx, unsigned short seqno, unsigned rtptime) { - ctx->record.seqno = seqno; - ctx->record.rtptime = rtptime; - ctx->record.time = gettime_ms(); +void rtp_record(rtp_t* ctx, unsigned short seqno, unsigned rtptime) { + ctx->record.seqno = seqno; + ctx->record.rtptime = rtptime; + ctx->record.time = gettime_ms(); - LOG_INFO("[%p]: record %hu %u", ctx, seqno, rtptime); + LOG_INFO("[%p]: record %hu %u", ctx, seqno, rtptime); } /*---------------------------------------------------------------------------*/ -static void buffer_alloc(abuf_t *audio_buffer, int size, uint8_t *buf, size_t buf_size) { - for (buffer_frames = 0; buf && buf_size >= size && buffer_frames < BUFFER_FRAMES_MAX; buffer_frames++) { - audio_buffer[buffer_frames].data = (s16_t*) buf; - audio_buffer[buffer_frames].allocated = 0; +static void buffer_alloc(abuf_t* audio_buffer, int size, uint8_t* buf, size_t buf_size) { + for(buffer_frames = 0; buf && buf_size >= size && buffer_frames < BUFFER_FRAMES_MAX; buffer_frames++) { + audio_buffer[buffer_frames].data = (s16_t*)buf; + audio_buffer[buffer_frames].allocated = 0; audio_buffer[buffer_frames].ready = 0; buf += size; buf_size -= size; - } - + } + LOG_INFO("allocated %d buffers (min=%d) from buffer of %zu bytes", buffer_frames, BUFFER_FRAMES_MIN, buf_size + buffer_frames * size); - + for(; buffer_frames < BUFFER_FRAMES_MIN; buffer_frames++) { - audio_buffer[buffer_frames].data = malloc(size); - audio_buffer[buffer_frames].allocated = 1; - audio_buffer[buffer_frames].ready = 0; - } + audio_buffer[buffer_frames].data = malloc(size); + audio_buffer[buffer_frames].allocated = 1; + audio_buffer[buffer_frames].ready = 0; + } } /*---------------------------------------------------------------------------*/ -static void buffer_release(abuf_t *audio_buffer) { - int i; - for (i = 0; i < buffer_frames; i++) { - if (audio_buffer[i].allocated) free(audio_buffer[i].data); - } +static void buffer_release(abuf_t* audio_buffer) { + int i; + for(i = 0; i < buffer_frames; i++) { + if(audio_buffer[i].allocated) free(audio_buffer[i].data); + } } /*---------------------------------------------------------------------------*/ -static void buffer_reset(abuf_t *audio_buffer) { - int i; - for (i = 0; i < buffer_frames; i++) audio_buffer[i].ready = 0; +static void buffer_reset(abuf_t* audio_buffer) { + int i; + for(i = 0; i < buffer_frames; i++) audio_buffer[i].ready = 0; } /*---------------------------------------------------------------------------*/ // the sequence numbers will wrap pretty often. // this returns true if the second arg is after the first static int seq_order(seq_t a, seq_t b) { - s16_t d = b - a; - return d > 0; + s16_t d = b - a; + return d > 0; } /*---------------------------------------------------------------------------*/ -static void alac_decode(rtp_t *ctx, s16_t *dest, char *buf, int len, u16_t *outsize) { - unsigned char iv[16]; - int aeslen; - assert(len<=MAX_PACKET); +static void alac_decode(rtp_t* ctx, s16_t* dest, char* buf, int len, u16_t* outsize) { + unsigned char iv[16]; + int aeslen; + assert(len <= MAX_PACKET); - if (ctx->decrypt) { - aeslen = len & ~0xf; - memcpy(iv, ctx->aesiv, sizeof(iv)); + if(ctx->decrypt) { + aeslen = len & ~0xf; + memcpy(iv, ctx->aesiv, sizeof(iv)); #ifdef WIN32 - AES_cbc_encrypt((unsigned char*)buf, ctx->decrypt_buf, aeslen, &ctx->aes, iv, AES_DECRYPT); + AES_cbc_encrypt((unsigned char*)buf, ctx->decrypt_buf, aeslen, &ctx->aes, iv, AES_DECRYPT); #else - mbedtls_aes_crypt_cbc(&ctx->aes, MBEDTLS_AES_DECRYPT, aeslen, iv, (unsigned char*) buf, ctx->decrypt_buf); + mbedtls_aes_crypt_cbc(&ctx->aes, MBEDTLS_AES_DECRYPT, aeslen, iv, (unsigned char*)buf, ctx->decrypt_buf); #endif - memcpy(ctx->decrypt_buf+aeslen, buf+aeslen, len-aeslen); - alac_to_pcm(ctx->alac_codec, (unsigned char*) ctx->decrypt_buf, (unsigned char*) dest, 2, (unsigned int*) outsize); - } else { - alac_to_pcm(ctx->alac_codec, (unsigned char*) buf, (unsigned char*) dest, 2, (unsigned int*) outsize); - } - - *outsize *= 4; + memcpy(ctx->decrypt_buf + aeslen, buf + aeslen, len - aeslen); + alac_to_pcm(ctx->alac_codec, (unsigned char*)ctx->decrypt_buf, (unsigned char*)dest, 2, (unsigned int*)outsize); + } else { + alac_to_pcm(ctx->alac_codec, (unsigned char*)buf, (unsigned char*)dest, 2, (unsigned int*)outsize); + } + + *outsize *= 4; } - /*---------------------------------------------------------------------------*/ -static void buffer_put_packet(rtp_t *ctx, seq_t seqno, unsigned rtptime, bool first, char *data, int len) { - abuf_t *abuf = NULL; - u32_t playtime; +static void buffer_put_packet(rtp_t* ctx, seq_t seqno, unsigned rtptime, bool first, char* data, int len) { + abuf_t* abuf = NULL; + u32_t playtime; - pthread_mutex_lock(&ctx->ab_mutex); + pthread_mutex_lock(&ctx->ab_mutex); - if (!ctx->playing) { - if ((ctx->flush_seqno == -1 || seq_order(ctx->flush_seqno, seqno)) && - (ctx->synchro.status & RTP_SYNC) && (ctx->synchro.status & NTP_SYNC)) { - ctx->ab_write = seqno-1; - ctx->ab_read = seqno; - ctx->flush_seqno = -1; - ctx->playing = true; - ctx->resent_req = ctx->resent_rec = ctx->silent_frames = ctx->discarded = 0; - playtime = ctx->synchro.time + ((rtptime - ctx->synchro.rtp) * 10) / (RAOP_SAMPLE_RATE / 100); - ctx->cmd_cb(RAOP_PLAY, playtime); - } else { - pthread_mutex_unlock(&ctx->ab_mutex); - return; - } - } + if(!ctx->playing) { + if((ctx->flush_seqno == -1 || seq_order(ctx->flush_seqno, seqno)) && (ctx->synchro.status & RTP_SYNC) && (ctx->synchro.status & NTP_SYNC)) { + ctx->ab_write = seqno - 1; + ctx->ab_read = seqno; + ctx->flush_seqno = -1; + ctx->playing = true; + ctx->resent_req = ctx->resent_rec = ctx->silent_frames = ctx->discarded = 0; + playtime = ctx->synchro.time + ((rtptime - ctx->synchro.rtp) * 10) / (RAOP_SAMPLE_RATE / 100); + ctx->cmd_cb(RAOP_PLAY, playtime); + } else { + pthread_mutex_unlock(&ctx->ab_mutex); + return; + } + } - if (seqno == (u16_t) (ctx->ab_write+1)) { - // expected packet - abuf = ctx->audio_buffer + BUFIDX(seqno); - ctx->ab_write = seqno; - LOG_SDEBUG("packet expected seqno:%hu rtptime:%u (W:%hu R:%hu)", seqno, rtptime, ctx->ab_write, ctx->ab_read); - } else if (seq_order(ctx->ab_write, seqno)) { - // newer than expected - if (ctx->latency && seq_order(ctx->latency / ctx->frame_size, seqno - ctx->ab_write - 1)) { - // this is a shitstorm, reset buffer + if(seqno == (u16_t)(ctx->ab_write + 1)) { + // expected packet + abuf = ctx->audio_buffer + BUFIDX(seqno); + ctx->ab_write = seqno; + LOG_SDEBUG("packet expected seqno:%hu rtptime:%u (W:%hu R:%hu)", seqno, rtptime, ctx->ab_write, ctx->ab_read); + } else if(seq_order(ctx->ab_write, seqno)) { + // newer than expected + if(ctx->latency && seq_order(ctx->latency / ctx->frame_size, seqno - ctx->ab_write - 1)) { + // this is a shitstorm, reset buffer LOG_WARN("[%p] too many missing frames %hu seq: %hu, (W:%hu R:%hu)", ctx, seqno - ctx->ab_write - 1, seqno, ctx->ab_write, ctx->ab_read); - ctx->ab_read = seqno; - } else { + ctx->ab_read = seqno; + } else { // request re-send missed frames and evaluate resent date as a whole *after* - rtp_request_resend(ctx, ctx->ab_write + 1, seqno-1); - + rtp_request_resend(ctx, ctx->ab_write + 1, seqno - 1); + // resend date is after all requests have been sent u32_t now = gettime_ms(); - + // set expected timing of missed frames for buffer_push_packet and set last_resend date - for (seq_t i = ctx->ab_write + 1; seq_order(i, seqno); i++) { - ctx->audio_buffer[BUFIDX(i)].rtptime = rtptime - (seqno-i)*ctx->frame_size; + for(seq_t i = ctx->ab_write + 1; seq_order(i, seqno); i++) { + ctx->audio_buffer[BUFIDX(i)].rtptime = rtptime - (seqno - i) * ctx->frame_size; ctx->audio_buffer[BUFIDX(i)].last_resend = now; } - LOG_DEBUG("[%p]: packet newer seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); - } + LOG_DEBUG("[%p]: packet newer seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); + } - abuf = ctx->audio_buffer + BUFIDX(seqno); - ctx->ab_write = seqno; - } else if (seq_order(ctx->ab_read, seqno + 1)) { - // recovered packet, not yet sent - abuf = ctx->audio_buffer + BUFIDX(seqno); - ctx->resent_rec++; - LOG_DEBUG("[%p]: packet recovered seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); - } else { - // too late - LOG_DEBUG("[%p]: packet too late seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); - } + abuf = ctx->audio_buffer + BUFIDX(seqno); + ctx->ab_write = seqno; + } else if(seq_order(ctx->ab_read, seqno + 1)) { + // recovered packet, not yet sent + abuf = ctx->audio_buffer + BUFIDX(seqno); + ctx->resent_rec++; + LOG_DEBUG("[%p]: packet recovered seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); + } else { + // too late + LOG_DEBUG("[%p]: packet too late seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); + } - if (ctx->in_frames++ > 1000) { - LOG_INFO("[%p]: fill [level:%hu rec:%u] [W:%hu R:%hu]", ctx, ctx->ab_write - ctx->ab_read, ctx->resent_rec, ctx->ab_write, ctx->ab_read); - ctx->in_frames = 0; - } + if(ctx->in_frames++ > 1000) { + LOG_INFO("[%p]: fill [level:%hu rec:%u] [W:%hu R:%hu]", ctx, ctx->ab_write - ctx->ab_read, ctx->resent_rec, ctx->ab_write, ctx->ab_read); + ctx->in_frames = 0; + } - if (abuf) { - alac_decode(ctx, abuf->data, data, len, &abuf->len); - abuf->ready = 1; - // this is the local rtptime when this frame is expected to play - abuf->rtptime = rtptime; - buffer_push_packet(ctx); + if(abuf) { + alac_decode(ctx, abuf->data, data, len, &abuf->len); + abuf->ready = 1; + // this is the local rtptime when this frame is expected to play + abuf->rtptime = rtptime; + buffer_push_packet(ctx); #ifdef __RTP_STORE - fwrite(data, len, 1, ctx->rtpIN); - fwrite(abuf->data, abuf->len, 1, ctx->rtpOUT); + fwrite(data, len, 1, ctx->rtpIN); + fwrite(abuf->data, abuf->len, 1, ctx->rtpOUT); #endif - } + } - pthread_mutex_unlock(&ctx->ab_mutex); + pthread_mutex_unlock(&ctx->ab_mutex); } /*---------------------------------------------------------------------------*/ // push as many frames as possible through callback -static void buffer_push_packet(rtp_t *ctx) { - abuf_t *curframe = NULL; - u32_t now, playtime, hold = max((ctx->latency * 1000) / (8 * RAOP_SAMPLE_RATE), 100); +static void buffer_push_packet(rtp_t* ctx) { + abuf_t* curframe = NULL; + u32_t now, playtime, hold = max((ctx->latency * 1000) / (8 * RAOP_SAMPLE_RATE), 100); - // not ready to play yet - if (!ctx->playing || ctx->synchro.status != (RTP_SYNC | NTP_SYNC)) return; + // not ready to play yet + if(!ctx->playing || ctx->synchro.status != (RTP_SYNC | NTP_SYNC)) return; - // there is always at least one frame in the buffer - do { - // re-evaluate time in loop in case data callback blocks ... - now = gettime_ms(); + // there is always at least one frame in the buffer + do { + // re-evaluate time in loop in case data callback blocks ... + now = gettime_ms(); - // try to manage playtime so that we overflow as late as possible if we miss NTP (2^31 / 10 / 44100) - curframe = ctx->audio_buffer + BUFIDX(ctx->ab_read); - playtime = ctx->synchro.time + ((curframe->rtptime - ctx->synchro.rtp) * 10) / (RAOP_SAMPLE_RATE / 100); + // try to manage playtime so that we overflow as late as possible if we miss NTP (2^31 / 10 / 44100) + curframe = ctx->audio_buffer + BUFIDX(ctx->ab_read); + playtime = ctx->synchro.time + ((curframe->rtptime - ctx->synchro.rtp) * 10) / (RAOP_SAMPLE_RATE / 100); - if (now > playtime) { - LOG_DEBUG("[%p]: discarded frame now:%u missed by:%d (W:%hu R:%hu)", ctx, now, now - playtime, ctx->ab_write, ctx->ab_read); - ctx->discarded++; - curframe->ready = 0; - } else if (playtime - now <= hold) { - if (curframe->ready) { - ctx->data_cb((const u8_t*) curframe->data, curframe->len, playtime); - curframe->ready = 0; - } else { - LOG_DEBUG("[%p]: created zero frame (W:%hu R:%hu)", ctx, ctx->ab_write, ctx->ab_read); - ctx->data_cb(silence_frame, ctx->frame_size * 4, playtime); - ctx->silent_frames++; - } - } else if (curframe->ready) { - ctx->data_cb((const u8_t*) curframe->data, curframe->len, playtime); - curframe->ready = 0; - } else { - break; - } + if(now > playtime) { + LOG_DEBUG("[%p]: discarded frame now:%u missed by:%d (W:%hu R:%hu)", ctx, now, now - playtime, ctx->ab_write, ctx->ab_read); + ctx->discarded++; + curframe->ready = 0; + } else if(playtime - now <= hold) { + if(curframe->ready) { + ctx->data_cb((const u8_t*)curframe->data, curframe->len, playtime); + curframe->ready = 0; + } else { + LOG_DEBUG("[%p]: created zero frame (W:%hu R:%hu)", ctx, ctx->ab_write, ctx->ab_read); + ctx->data_cb(silence_frame, ctx->frame_size * 4, playtime); + ctx->silent_frames++; + } + } else if(curframe->ready) { + ctx->data_cb((const u8_t*)curframe->data, curframe->len, playtime); + curframe->ready = 0; + } else { + break; + } - ctx->ab_read++; - ctx->out_frames++; + ctx->ab_read++; + ctx->out_frames++; - } while (seq_order(ctx->ab_read, ctx->ab_write)); + } while(seq_order(ctx->ab_read, ctx->ab_write)); - if (ctx->out_frames > 1000) { - LOG_INFO("[%p]: drain [level:%hd head:%d ms] [W:%hu R:%hu] [req:%u sil:%u dis:%u]", - ctx, ctx->ab_write - ctx->ab_read, playtime - now, ctx->ab_write, ctx->ab_read, - ctx->resent_req, ctx->silent_frames, ctx->discarded); - ctx->out_frames = 0; - } + if(ctx->out_frames > 1000) { + LOG_INFO("[%p]: drain [level:%hd head:%d ms] [W:%hu R:%hu] [req:%u sil:%u dis:%u]", ctx, ctx->ab_write - ctx->ab_read, playtime - now, + ctx->ab_write, ctx->ab_read, ctx->resent_req, ctx->silent_frames, ctx->discarded); + ctx->out_frames = 0; + } - LOG_SDEBUG("playtime %u %d [W:%hu R:%hu] %d", playtime, playtime - now, ctx->ab_write, ctx->ab_read, curframe->ready); + LOG_SDEBUG("playtime %u %d [W:%hu R:%hu] %d", playtime, playtime - now, ctx->ab_write, ctx->ab_read, curframe->ready); - // each missing packet will be requested up to (latency_frames / 16) times - for (int i = 0; seq_order(ctx->ab_read + i, ctx->ab_write); i += 16) { - abuf_t *frame = ctx->audio_buffer + BUFIDX(ctx->ab_read + i); - if (!frame->ready && now - frame->last_resend > RESEND_TO) { + // each missing packet will be requested up to (latency_frames / 16) times + for(int i = 0; seq_order(ctx->ab_read + i, ctx->ab_write); i += 16) { + abuf_t* frame = ctx->audio_buffer + BUFIDX(ctx->ab_read + i); + if(!frame->ready && now - frame->last_resend > RESEND_TO) { // stop if one fails - if (!rtp_request_resend(ctx, ctx->ab_read + i, ctx->ab_read + i)) break; - frame->last_resend = now; - } - } - } - + if(!rtp_request_resend(ctx, ctx->ab_read + i, ctx->ab_read + i)) break; + frame->last_resend = now; + } + } +} /*---------------------------------------------------------------------------*/ #ifdef WIN32 -static void *rtp_thread_func(void *arg) { -#else -static void rtp_thread_func(void *arg) { -#endif - fd_set fds; - int i, sock = -1; - int count = 0; - bool ntp_sent; - char *packet = malloc(MAX_PACKET); - rtp_t *ctx = (rtp_t*) arg; +static void* rtp_thread_func(void* arg) { +#else +static void rtp_thread_func(void* arg) { +#endif + fd_set fds; + int i, sock = -1; + int count = 0; + bool ntp_sent; + char* packet = malloc(MAX_PACKET); + rtp_t* ctx = (rtp_t*)arg; - for (i = 0; i < 3; i++) { - if (ctx->rtp_sockets[i].sock > sock) sock = ctx->rtp_sockets[i].sock; - // send synchro request 3 times - ntp_sent = rtp_request_timing(ctx); - } + for(i = 0; i < 3; i++) { + if(ctx->rtp_sockets[i].sock > sock) sock = ctx->rtp_sockets[i].sock; + // send synchro request 3 times + ntp_sent = rtp_request_timing(ctx); + } - while (ctx->running) { - ssize_t plen; - char type; - socklen_t rtp_client_len = sizeof(struct sockaddr_in); - int idx = 0; - char *pktp = packet; - struct timeval timeout = {0, 100*1000}; + while(ctx->running) { + ssize_t plen; + char type; + socklen_t rtp_client_len = sizeof(struct sockaddr_in); + int idx = 0; + char* pktp = packet; + struct timeval timeout = {0, 100 * 1000}; - FD_ZERO(&fds); - for (i = 0; i < 3; i++) { FD_SET(ctx->rtp_sockets[i].sock, &fds); } + FD_ZERO(&fds); + for(i = 0; i < 3; i++) { FD_SET(ctx->rtp_sockets[i].sock, &fds); } - if (select(sock + 1, &fds, NULL, NULL, &timeout) <= 0) { - if (ctx->stalled++ == 30*10) ctx->cmd_cb(RAOP_STALLED); + if(select(sock + 1, &fds, NULL, NULL, &timeout) <= 0) { + if(ctx->stalled++ == 30 * 10) ctx->cmd_cb(RAOP_STALLED); continue; } - for (i = 0; i < 3; i++) - if (FD_ISSET(ctx->rtp_sockets[i].sock, &fds)) idx = i; + for(i = 0; i < 3; i++) + if(FD_ISSET(ctx->rtp_sockets[i].sock, &fds)) idx = i; - plen = recvfrom(ctx->rtp_sockets[idx].sock, packet, MAX_PACKET, MSG_DONTWAIT, (struct sockaddr*) &ctx->rtp_host, &rtp_client_len); + plen = recvfrom(ctx->rtp_sockets[idx].sock, packet, MAX_PACKET, MSG_DONTWAIT, (struct sockaddr*)&ctx->rtp_host, &rtp_client_len); - if (!ntp_sent) { - LOG_WARN("[%p]: NTP request not send yet", ctx); - ntp_sent = rtp_request_timing(ctx); - } + if(!ntp_sent) { + LOG_WARN("[%p]: NTP request not send yet", ctx); + ntp_sent = rtp_request_timing(ctx); + } - if (plen <= 0) { - LOG_WARN("Nothing received on a readable socket %d", plen); - continue; - } - - assert(plen <= MAX_PACKET); + if(plen <= 0) { + LOG_WARN("Nothing received on a readable socket %d", plen); + continue; + } + + assert(plen <= MAX_PACKET); ctx->stalled = 0; - type = packet[1] & ~0x80; - pktp = packet; + type = packet[1] & ~0x80; + pktp = packet; - switch (type) { - seq_t seqno; - unsigned rtptime; + switch(type) { + seq_t seqno; + unsigned rtptime; - // re-sent packet - case 0x56: { - pktp += 4; - plen -= 4; - } - // fall through - - // data packet - case 0x60: { - seqno = ntohs(*(u16_t*)(pktp+2)); - rtptime = ntohl(*(u32_t*)(pktp+4)); + // re-sent packet + case 0x56: { + pktp += 4; + plen -= 4; + } + // fall through - // adjust pointer and length - pktp += 12; - plen -= 12; + // data packet + case 0x60: { + seqno = ntohs(*(u16_t*)(pktp + 2)); + rtptime = ntohl(*(u32_t*)(pktp + 4)); - LOG_SDEBUG("[%p]: seqno:%hu rtp:%u (type: %x, first: %u)", ctx, seqno, rtptime, type, packet[1] & 0x80); + // adjust pointer and length + pktp += 12; + plen -= 12; - // check if packet contains enough content to be reasonable - if (plen < 16) break; + LOG_SDEBUG("[%p]: seqno:%hu rtp:%u (type: %x, first: %u)", ctx, seqno, rtptime, type, packet[1] & 0x80); - if ((packet[1] & 0x80) && (type != 0x56)) { - LOG_INFO("[%p]: 1st audio packet received", ctx); - } + // check if packet contains enough content to be reasonable + if(plen < 16) break; - buffer_put_packet(ctx, seqno, rtptime, packet[1] & 0x80, pktp, plen); + if((packet[1] & 0x80) && (type != 0x56)) { LOG_INFO("[%p]: 1st audio packet received", ctx); } - break; - } + buffer_put_packet(ctx, seqno, rtptime, packet[1] & 0x80, pktp, plen); - // sync packet - case 0x54: { - u32_t rtp_now_latency = ntohl(*(u32_t*)(pktp+4)); - u64_t remote = (((u64_t) ntohl(*(u32_t*)(pktp+8))) << 32) + ntohl(*(u32_t*)(pktp+12)); - u32_t rtp_now = ntohl(*(u32_t*)(pktp+16)); - u16_t flags = ntohs(*(u16_t*)(pktp+2)); - u32_t remote_gap = NTP2MS(remote - ctx->timing.remote); + break; + } - // try to get NTP every 3 sec or every time if we are not synced - if (!count-- || !(ctx->synchro.status & NTP_SYNC)) { - rtp_request_timing(ctx); - count = 3; - } + // sync packet + case 0x54: { + u32_t rtp_now_latency = ntohl(*(u32_t*)(pktp + 4)); + u64_t remote = (((u64_t)ntohl(*(u32_t*)(pktp + 8))) << 32) + ntohl(*(u32_t*)(pktp + 12)); + u32_t rtp_now = ntohl(*(u32_t*)(pktp + 16)); + u16_t flags = ntohs(*(u16_t*)(pktp + 2)); + u32_t remote_gap = NTP2MS(remote - ctx->timing.remote); - // something is wrong, we should not have such gap - if (remote_gap > 10000) { - LOG_WARN("discarding remote timing information %u", remote_gap); - break; - } + // try to get NTP every 3 sec or every time if we are not synced + if(!count-- || !(ctx->synchro.status & NTP_SYNC)) { + rtp_request_timing(ctx); + count = 3; + } - pthread_mutex_lock(&ctx->ab_mutex); + // something is wrong, we should not have such gap + if(remote_gap > 10000) { + LOG_WARN("discarding remote timing information %u", remote_gap); + break; + } - // re-align timestamp and expected local playback time (and magic 11025 latency) - ctx->latency = rtp_now - rtp_now_latency; - if (flags == 7 || flags == 4) ctx->latency += 11025; - if (ctx->latency < MIN_LATENCY) ctx->latency = MIN_LATENCY; - else if (ctx->latency > MAX_LATENCY) ctx->latency = MAX_LATENCY; - ctx->synchro.rtp = rtp_now - ctx->latency; - ctx->synchro.time = ctx->timing.local + remote_gap; + pthread_mutex_lock(&ctx->ab_mutex); - // now we are synced on RTP frames - ctx->synchro.status |= RTP_SYNC; + // re-align timestamp and expected local playback time (and magic 11025 latency) + ctx->latency = rtp_now - rtp_now_latency; + if(flags == 7 || flags == 4) ctx->latency += 11025; + if(ctx->latency < MIN_LATENCY) + ctx->latency = MIN_LATENCY; + else if(ctx->latency > MAX_LATENCY) + ctx->latency = MAX_LATENCY; + ctx->synchro.rtp = rtp_now - ctx->latency; + ctx->synchro.time = ctx->timing.local + remote_gap; - // 1st sync packet received (signals a restart of playback) - if (packet[0] & 0x10) { - LOG_INFO("[%p]: 1st sync packet received", ctx); - } + // now we are synced on RTP frames + ctx->synchro.status |= RTP_SYNC; - pthread_mutex_unlock(&ctx->ab_mutex); + // 1st sync packet received (signals a restart of playback) + if(packet[0] & 0x10) { LOG_INFO("[%p]: 1st sync packet received", ctx); } - LOG_DEBUG("[%p]: sync packet latency:%d rtp_latency:%u rtp:%u remote ntp:%llx, local time:%u local rtp:%u (now:%u)", - ctx, ctx->latency, rtp_now_latency, rtp_now, remote, ctx->synchro.time, ctx->synchro.rtp, gettime_ms()); + pthread_mutex_unlock(&ctx->ab_mutex); - if ((ctx->synchro.status & RTP_SYNC) && (ctx->synchro.status & NTP_SYNC)) ctx->cmd_cb(RAOP_TIMING); + LOG_DEBUG("[%p]: sync packet latency:%d rtp_latency:%u rtp:%u remote ntp:%llx, local time:%u local rtp:%u (now:%u)", ctx, ctx->latency, + rtp_now_latency, rtp_now, remote, ctx->synchro.time, ctx->synchro.rtp, gettime_ms()); - break; - } + if((ctx->synchro.status & RTP_SYNC) && (ctx->synchro.status & NTP_SYNC)) ctx->cmd_cb(RAOP_TIMING); - // NTP timing packet - case 0x53: { - u32_t reference = ntohl(*(u32_t*)(pktp+12)); // only low 32 bits in our case - u64_t remote =(((u64_t) ntohl(*(u32_t*)(pktp+16))) << 32) + ntohl(*(u32_t*)(pktp+20)); - u32_t roundtrip = gettime_ms() - reference; - - // better discard sync packets when roundtrip is suspicious - if (roundtrip > 100) { - // ask for another one only if we are not synced already - if (!(ctx->synchro.status & NTP_SYNC)) rtp_request_timing(ctx); - LOG_WARN("[%p]: discarding NTP roundtrip of %u ms", ctx, roundtrip); - break; - } + break; + } - /* + // NTP timing packet + case 0x53: { + u32_t reference = ntohl(*(u32_t*)(pktp + 12)); // only low 32 bits in our case + u64_t remote = (((u64_t)ntohl(*(u32_t*)(pktp + 16))) << 32) + ntohl(*(u32_t*)(pktp + 20)); + u32_t roundtrip = gettime_ms() - reference; + + // better discard sync packets when roundtrip is suspicious + if(roundtrip > 100) { + // ask for another one only if we are not synced already + if(!(ctx->synchro.status & NTP_SYNC)) rtp_request_timing(ctx); + LOG_WARN("[%p]: discarding NTP roundtrip of %u ms", ctx, roundtrip); + break; + } + + /* The expected elapsed remote time should be exactly the same as elapsed local time between the two request, corrected by the drifting u64_t expected = ctx->timing.remote + MS2NTP(reference - ctx->timing.local); */ - ctx->timing.remote = remote; - ctx->timing.local = reference; + ctx->timing.remote = remote; + ctx->timing.local = reference; - // now we are synced on NTP (mutex not needed) - ctx->synchro.status |= NTP_SYNC; + // now we are synced on NTP (mutex not needed) + ctx->synchro.status |= NTP_SYNC; - LOG_DEBUG("[%p]: Timing references local:%llu, remote:%llx (delta:%lld, sum:%lld, adjust:%lld, gaps:%d)", - ctx, ctx->timing.local, ctx->timing.remote); + LOG_DEBUG("[%p]: Timing references local:%llu, remote:%llx (delta:%lld, sum:%lld, adjust:%lld, gaps:%d)", ctx, ctx->timing.local, + ctx->timing.remote); - break; - } - - default: { - LOG_WARN("Unknown packet received %x", (int) type); - break; - } - } - } + break; + } - free(packet); - LOG_INFO("[%p]: terminating", ctx); + default: { + LOG_WARN("Unknown packet received %x", (int)type); + break; + } + } + } + + free(packet); + LOG_INFO("[%p]: terminating", ctx); #ifndef WIN32 - xTaskNotifyGive(ctx->joiner); - vTaskSuspend(NULL); -#else - return NULL; + xTaskNotifyGive(ctx->joiner); + vTaskSuspend(NULL); +#else + return NULL; #endif } /*---------------------------------------------------------------------------*/ -static bool rtp_request_timing(rtp_t *ctx) { - unsigned char req[32]; - u32_t now = gettime_ms(); - int i; - struct sockaddr_in host; +static bool rtp_request_timing(rtp_t* ctx) { + unsigned char req[32]; + u32_t now = gettime_ms(); + int i; + struct sockaddr_in host; - LOG_DEBUG("[%p]: timing request now:%u (port: %hu)", ctx, now, ctx->rtp_sockets[TIMING].rport); + LOG_DEBUG("[%p]: timing request now:%u (port: %hu)", ctx, now, ctx->rtp_sockets[TIMING].rport); - req[0] = 0x80; - req[1] = 0x52|0x80; - *(u16_t*)(req+2) = htons(7); - *(u32_t*)(req+4) = htonl(0); // dummy - for (i = 0; i < 16; i++) req[i+8] = 0; - *(u32_t*)(req+24) = 0; - *(u32_t*)(req+28) = htonl(now); // this is not a real NTP, but a 32 ms counter in the low part of the NTP + req[0] = 0x80; + req[1] = 0x52 | 0x80; + *(u16_t*)(req + 2) = htons(7); + *(u32_t*)(req + 4) = htonl(0); // dummy + for(i = 0; i < 16; i++) req[i + 8] = 0; + *(u32_t*)(req + 24) = 0; + *(u32_t*)(req + 28) = htonl(now); // this is not a real NTP, but a 32 ms counter in the low part of the NTP - if (ctx->host.s_addr != INADDR_ANY) { - host.sin_family = AF_INET; - host.sin_addr = ctx->host; - } else host = ctx->rtp_host; + if(ctx->host.s_addr != INADDR_ANY) { + host.sin_family = AF_INET; + host.sin_addr = ctx->host; + } else + host = ctx->rtp_host; - // no address from sender, need to wait for 1st packet to be received - if (host.sin_addr.s_addr == INADDR_ANY) return false; + // no address from sender, need to wait for 1st packet to be received + if(host.sin_addr.s_addr == INADDR_ANY) return false; - host.sin_port = htons(ctx->rtp_sockets[TIMING].rport); + host.sin_port = htons(ctx->rtp_sockets[TIMING].rport); - if (sizeof(req) != sendto(ctx->rtp_sockets[TIMING].sock, req, sizeof(req), MSG_DONTWAIT, (struct sockaddr*) &host, sizeof(host))) { - LOG_WARN("[%p]: SENDTO failed (%s)", ctx, strerror(errno)); - } + if(sizeof(req) != sendto(ctx->rtp_sockets[TIMING].sock, req, sizeof(req), MSG_DONTWAIT, (struct sockaddr*)&host, sizeof(host))) { + LOG_WARN("[%p]: SENDTO failed (%s)", ctx, strerror(errno)); + } - return true; + return true; } /*---------------------------------------------------------------------------*/ -static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) { - unsigned char req[8]; // *not* a standard RTCP NACK +static bool rtp_request_resend(rtp_t* ctx, seq_t first, seq_t last) { + unsigned char req[8]; // *not* a standard RTCP NACK - // do not request silly ranges (happens in case of network large blackouts) - if (seq_order(last, first) || last - first > buffer_frames / 2) return false; - - ctx->resent_req += (seq_t) (last - first) + 1; + // do not request silly ranges (happens in case of network large blackouts) + if(seq_order(last, first) || last - first > buffer_frames / 2) return false; - LOG_DEBUG("resend request [W:%hu R:%hu first=%hu last=%hu]", ctx->ab_write, ctx->ab_read, first, last); + ctx->resent_req += (seq_t)(last - first) + 1; - req[0] = 0x80; - req[1] = 0x55|0x80; // Apple 'resend' - *(u16_t*)(req+2) = htons(1); // our seqnum - *(u16_t*)(req+4) = htons(first); // missed seqnum - *(u16_t*)(req+6) = htons(last-first+1); // count + LOG_DEBUG("resend request [W:%hu R:%hu first=%hu last=%hu]", ctx->ab_write, ctx->ab_read, first, last); - ctx->rtp_host.sin_port = htons(ctx->rtp_sockets[CONTROL].rport); + req[0] = 0x80; + req[1] = 0x55 | 0x80; // Apple 'resend' + *(u16_t*)(req + 2) = htons(1); // our seqnum + *(u16_t*)(req + 4) = htons(first); // missed seqnum + *(u16_t*)(req + 6) = htons(last - first + 1); // count - if (sizeof(req) != sendto(ctx->rtp_sockets[CONTROL].sock, req, sizeof(req), MSG_DONTWAIT, (struct sockaddr*) &ctx->rtp_host, sizeof(ctx->rtp_host))) { - LOG_WARN("[%p]: SENDTO failed (%s)", ctx, strerror(errno)); + ctx->rtp_host.sin_port = htons(ctx->rtp_sockets[CONTROL].rport); + + if(sizeof(req) != + sendto(ctx->rtp_sockets[CONTROL].sock, req, sizeof(req), MSG_DONTWAIT, (struct sockaddr*)&ctx->rtp_host, sizeof(ctx->rtp_host))) { + LOG_WARN("[%p]: SENDTO failed (%s)", ctx, strerror(errno)); return false; - } + } - return true; + return true; } diff --git a/components/raop/rtp.h b/components/raop/rtp.h index a28e1d8a..20accd7a 100644 --- a/components/raop/rtp.h +++ b/components/raop/rtp.h @@ -5,19 +5,16 @@ #include "util.h" typedef struct { - unsigned short cport, tport, aport; - struct rtp_s *ctx; + unsigned short cport, tport, aport; + struct rtp_s* ctx; } rtp_resp_t; -rtp_resp_t rtp_init(struct in_addr host, int latency, - char *aeskey, char *aesiv, char *fmtpstr, - short unsigned pCtrlPort, short unsigned pTimingPort, - uint8_t *buffer, size_t size, - raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb); -void rtp_end(struct rtp_s *ctx); -bool rtp_flush(struct rtp_s *ctx, unsigned short seqno, unsigned rtptime, bool exit_locked); -void rtp_flush_release(struct rtp_s *ctx); -void rtp_record(struct rtp_s *ctx, unsigned short seqno, unsigned rtptime); -void rtp_metadata(struct rtp_s *ctx, struct metadata_s *metadata); +rtp_resp_t rtp_init(struct in_addr host, int latency, char* aeskey, char* aesiv, char* fmtpstr, short unsigned pCtrlPort, short unsigned pTimingPort, + uint8_t* buffer, size_t size, raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb); +void rtp_end(struct rtp_s* ctx); +bool rtp_flush(struct rtp_s* ctx, unsigned short seqno, unsigned rtptime, bool exit_locked); +void rtp_flush_release(struct rtp_s* ctx); +void rtp_record(struct rtp_s* ctx, unsigned short seqno, unsigned rtptime); +void rtp_metadata(struct rtp_s* ctx, struct metadata_s* metadata); #endif diff --git a/components/raop/util.c b/components/raop/util.c index e01ca258..0535fbd8 100644 --- a/components/raop/util.c +++ b/components/raop/util.c @@ -29,15 +29,15 @@ /* globals */ /*----------------------------------------------------------------------------*/ -extern log_level util_loglevel; +extern log_level util_loglevel; /*----------------------------------------------------------------------------*/ /* locals */ /*----------------------------------------------------------------------------*/ -static log_level *loglevel = &util_loglevel; +static log_level* loglevel = &util_loglevel; -static char *ltrim(char *s); -static int read_line(int fd, char *line, int maxlen, int timeout); +static char* ltrim(char* s); +static int read_line(int fd, char* line, int maxlen, int timeout); /*----------------------------------------------------------------------------*/ /* */ @@ -51,148 +51,136 @@ static int read_line(int fd, char *line, int maxlen, int timeout); #if !defined(WIN32) #define INVALID_SOCKET (-1) #endif -in_addr_t get_localhost(char **name) -{ +in_addr_t get_localhost(char** name) { #ifdef WIN32 - char buf[256]; - struct hostent *h = NULL; - struct sockaddr_in LocalAddr; + char buf[256]; + struct hostent* h = NULL; + struct sockaddr_in LocalAddr; - memset(&LocalAddr, 0, sizeof(LocalAddr)); + memset(&LocalAddr, 0, sizeof(LocalAddr)); - gethostname(buf, 256); - h = gethostbyname(buf); + gethostname(buf, 256); + h = gethostbyname(buf); - if (name) *name = strdup(buf); + if(name) *name = strdup(buf); - if (h != NULL) { - memcpy(&LocalAddr.sin_addr, h->h_addr_list[0], 4); - return LocalAddr.sin_addr.s_addr; - } - else return INADDR_ANY; + if(h != NULL) { + memcpy(&LocalAddr.sin_addr, h->h_addr_list[0], 4); + return LocalAddr.sin_addr.s_addr; + } else + return INADDR_ANY; #else - tcpip_adapter_ip_info_t ipInfo; - tcpip_adapter_if_t if_type = TCPIP_ADAPTER_IF_STA; + tcpip_adapter_ip_info_t ipInfo; + tcpip_adapter_if_t if_type = TCPIP_ADAPTER_IF_STA; - // then get IP address - tcpip_adapter_get_ip_info(if_type, &ipInfo); - - // we might be in AP mode - if (ipInfo.ip.addr == INADDR_ANY) { - if_type = TCPIP_ADAPTER_IF_AP; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ipInfo); - } + // then get IP address + tcpip_adapter_get_ip_info(if_type, &ipInfo); - // get hostname if required - if (name) { - const char *hostname; - tcpip_adapter_get_hostname(if_type, &hostname); - *name = strdup(hostname); - } + // we might be in AP mode + if(ipInfo.ip.addr == INADDR_ANY) { + if_type = TCPIP_ADAPTER_IF_AP; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ipInfo); + } - return ipInfo.ip.addr; + // get hostname if required + if(name) { + const char* hostname; + tcpip_adapter_get_hostname(if_type, &hostname); + *name = strdup(hostname); + } + + return ipInfo.ip.addr; #endif } - /*----------------------------------------------------------------------------*/ #ifdef WIN32 void winsock_init(void) { - WSADATA wsaData; - WORD wVersionRequested = MAKEWORD(2, 2); - int WSerr = WSAStartup(wVersionRequested, &wsaData); - if (WSerr != 0) { - LOG_ERROR("Bad winsock version", NULL); - exit(1); - } + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(2, 2); + int WSerr = WSAStartup(wVersionRequested, &wsaData); + if(WSerr != 0) { + LOG_ERROR("Bad winsock version", NULL); + exit(1); + } } /*----------------------------------------------------------------------------*/ -void winsock_close(void) { - WSACleanup(); -} +void winsock_close(void) { WSACleanup(); } #endif - /*----------------------------------------------------------------------------*/ -int shutdown_socket(int sd) -{ - if (sd <= 0) return -1; +int shutdown_socket(int sd) { + if(sd <= 0) return -1; #ifdef WIN32 - shutdown(sd, SD_BOTH); + shutdown(sd, SD_BOTH); #else - shutdown(sd, SHUT_RDWR); + shutdown(sd, SHUT_RDWR); #endif - LOG_DEBUG("closed socket %d", sd); + LOG_DEBUG("closed socket %d", sd); - return closesocket(sd); + return closesocket(sd); } - /*----------------------------------------------------------------------------*/ -int bind_socket(unsigned short *port, int mode) -{ - int sock; - socklen_t len = sizeof(struct sockaddr); - struct sockaddr_in addr; +int bind_socket(unsigned short* port, int mode) { + int sock; + socklen_t len = sizeof(struct sockaddr); + struct sockaddr_in addr; - if ((sock = socket(AF_INET, mode, 0)) < 0) { - LOG_ERROR("cannot create socket %d", sock); - return sock; - } + if((sock = socket(AF_INET, mode, 0)) < 0) { + LOG_ERROR("cannot create socket %d", sock); + return sock; + } - /* Populate socket address structure */ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(*port); + /* Populate socket address structure */ + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(*port); #ifdef SIN_LEN - si.sin_len = sizeof(si); + si.sin_len = sizeof(si); #endif - if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) { - closesocket(sock); - LOG_ERROR("cannot bind socket %d", sock); - return -1; - } + if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + closesocket(sock); + LOG_ERROR("cannot bind socket %d", sock); + return -1; + } - if (!*port) { - getsockname(sock, (struct sockaddr *) &addr, &len); - *port = ntohs(addr.sin_port); - } + if(!*port) { + getsockname(sock, (struct sockaddr*)&addr, &len); + *port = ntohs(addr.sin_port); + } - LOG_DEBUG("socket binding %d on port %d", sock, *port); + LOG_DEBUG("socket binding %d on port %d", sock, *port); - return sock; + return sock; } - /*----------------------------------------------------------------------------*/ -int conn_socket(unsigned short port) -{ - struct sockaddr_in addr; - int sd; +int conn_socket(unsigned short port) { + struct sockaddr_in addr; + int sd; - sd = socket(AF_INET, SOCK_STREAM, 0); + sd = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(port); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(port); - if (sd < 0 || connect(sd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(sd); - return -1; - } + if(sd < 0 || connect(sd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + close(sd); + return -1; + } - LOG_DEBUG("created socket %d", sd); + LOG_DEBUG("created socket %d", sd); - return sd; + return sd; } - - /*----------------------------------------------------------------------------*/ /* */ /* SYSTEM utils */ @@ -201,31 +189,30 @@ int conn_socket(unsigned short port) #ifdef WIN32 /*----------------------------------------------------------------------------*/ -void *dlopen(const char *filename, int flag) { - SetLastError(0); - return LoadLibrary((LPCTSTR)filename); +void* dlopen(const char* filename, int flag) { + SetLastError(0); + return LoadLibrary((LPCTSTR)filename); } /*----------------------------------------------------------------------------*/ -void *dlsym(void *handle, const char *symbol) { - SetLastError(0); - return (void *)GetProcAddress(handle, symbol); +void* dlsym(void* handle, const char* symbol) { + SetLastError(0); + return (void*)GetProcAddress(handle, symbol); } /*----------------------------------------------------------------------------*/ -char *dlerror(void) { - static char ret[32]; - int last = GetLastError(); - if (last) { - sprintf(ret, "code: %i", last); - SetLastError(0); - return ret; - } - return NULL; +char* dlerror(void) { + static char ret[32]; + int last = GetLastError(); + if(last) { + sprintf(ret, "code: %i", last); + SetLastError(0); + return ret; + } + return NULL; } #endif - /*----------------------------------------------------------------------------*/ /* */ /* STDLIB extensions */ @@ -234,116 +221,105 @@ char *dlerror(void) { #ifdef WIN32 /*---------------------------------------------------------------------------*/ -char *strcasestr(const char *haystack, const char *needle) { - size_t length_needle; - size_t length_haystack; - size_t i; +char* strcasestr(const char* haystack, const char* needle) { + size_t length_needle; + size_t length_haystack; + size_t i; - if (!haystack || !needle) - return NULL; + if(!haystack || !needle) return NULL; - length_needle = strlen(needle); - length_haystack = strlen(haystack); + length_needle = strlen(needle); + length_haystack = strlen(haystack); - if (length_haystack < length_needle) return NULL; + if(length_haystack < length_needle) return NULL; - length_haystack -= length_needle - 1; + length_haystack -= length_needle - 1; - for (i = 0; i < length_haystack; i++) - { - size_t j; + for(i = 0; i < length_haystack; i++) { + size_t j; - for (j = 0; j < length_needle; j++) - { - unsigned char c1; - unsigned char c2; + for(j = 0; j < length_needle; j++) { + unsigned char c1; + unsigned char c2; - c1 = haystack[i+j]; - c2 = needle[j]; - if (toupper(c1) != toupper(c2)) - goto next; - } - return (char *) haystack + i; - next: - ; - } + c1 = haystack[i + j]; + c2 = needle[j]; + if(toupper(c1) != toupper(c2)) goto next; + } + return (char*)haystack + i; + next:; + } - return NULL; + return NULL; } /*---------------------------------------------------------------------------*/ -char* strsep(char** stringp, const char* delim) -{ - char* start = *stringp; - char* p; +char* strsep(char** stringp, const char* delim) { + char* start = *stringp; + char* p; - p = (start != NULL) ? strpbrk(start, delim) : NULL; + p = (start != NULL) ? strpbrk(start, delim) : NULL; - if (p == NULL) { - *stringp = NULL; - } else { - *p = '\0'; - *stringp = p + 1; - } + if(p == NULL) { + *stringp = NULL; + } else { + *p = '\0'; + *stringp = p + 1; + } - return start; + return start; } /*---------------------------------------------------------------------------*/ -char *strndup(const char *s, size_t n) { - char *p = malloc(n + 1); - strncpy(p, s, n); - p[n] = '\0'; +char* strndup(const char* s, size_t n) { + char* p = malloc(n + 1); + strncpy(p, s, n); + p[n] = '\0'; - return p; + return p; } #endif - /*----------------------------------------------------------------------------*/ -char* strextract(char *s1, char *beg, char *end) -{ - char *p1, *p2, *res; +char* strextract(char* s1, char* beg, char* end) { + char *p1, *p2, *res; - p1 = strcasestr(s1, beg); - if (!p1) return NULL; + p1 = strcasestr(s1, beg); + if(!p1) return NULL; - p1 += strlen(beg); - p2 = strcasestr(p1, end); - if (!p2) return strdup(p1); + p1 += strlen(beg); + p2 = strcasestr(p1, end); + if(!p2) return strdup(p1); - res = malloc(p2 - p1 + 1); - memcpy(res, p1, p2 - p1); - res[p2 - p1] = '\0'; + res = malloc(p2 - p1 + 1); + memcpy(res, p1, p2 - p1); + res[p2 - p1] = '\0'; - return res; + return res; } - #ifdef WIN32 /*----------------------------------------------------------------------------*/ -int asprintf(char **strp, const char *fmt, ...) -{ - va_list args, cp; - int len, ret = 0; +int asprintf(char** strp, const char* fmt, ...) { + va_list args, cp; + int len, ret = 0; - va_start(args, fmt); - len = vsnprintf(NULL, 0, fmt, args); - *strp = malloc(len + 1); + va_start(args, fmt); + len = vsnprintf(NULL, 0, fmt, args); + *strp = malloc(len + 1); - if (*strp) ret = vsprintf(*strp, fmt, args); + if(*strp) ret = vsprintf(*strp, fmt, args); - va_end(args); + va_end(args); - return ret; + return ret; } #endif /*---------------------------------------------------------------------------*/ -static char *ltrim(char *s) -{ - while(isspace((int) *s)) s++; - return s; +static char* ltrim(char* s) { + while(isspace((int)*s)) s++; + return s; } /*----------------------------------------------------------------------------*/ @@ -353,254 +329,229 @@ static char *ltrim(char *s) /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ -bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len) -{ - char line[256], *dp; - unsigned j; - int i, timeout = 100; +bool http_parse(int sock, char* method, key_data_t* rkd, char** body, int* len) { + char line[256], *dp; + unsigned j; + int i, timeout = 100; - rkd[0].key = NULL; + rkd[0].key = NULL; - if ((i = read_line(sock, line, sizeof(line), timeout)) <= 0) { - if (i < 0) { - LOG_ERROR("cannot read method", NULL); - } - return false; - } + if((i = read_line(sock, line, sizeof(line), timeout)) <= 0) { + if(i < 0) { LOG_ERROR("cannot read method", NULL); } + return false; + } - if (!sscanf(line, "%s", method)) { - LOG_ERROR("missing method", NULL); - return false; - } + if(!sscanf(line, "%s", method)) { + LOG_ERROR("missing method", NULL); + return false; + } - i = *len = 0; + i = *len = 0; - while (read_line(sock, line, sizeof(line), timeout) > 0) { + while(read_line(sock, line, sizeof(line), timeout) > 0) { - LOG_SDEBUG("sock: %u, received %s", line); + LOG_SDEBUG("sock: %u, received %s", line); - // line folding should be deprecated - if (i && rkd[i].key && (line[0] == ' ' || line[0] == '\t')) { - for(j = 0; j < strlen(line); j++) if (line[j] != ' ' && line[j] != '\t') break; - rkd[i].data = realloc(rkd[i].data, strlen(rkd[i].data) + strlen(line + j) + 1); - strcat(rkd[i].data, line + j); - continue; - } + // line folding should be deprecated + if(i && rkd[i].key && (line[0] == ' ' || line[0] == '\t')) { + for(j = 0; j < strlen(line); j++) + if(line[j] != ' ' && line[j] != '\t') break; + rkd[i].data = realloc(rkd[i].data, strlen(rkd[i].data) + strlen(line + j) + 1); + strcat(rkd[i].data, line + j); + continue; + } - dp = strstr(line,":"); + dp = strstr(line, ":"); - if (!dp){ - LOG_ERROR("Request failed, bad header", NULL); - kd_free(rkd); - return false; - } + if(!dp) { + LOG_ERROR("Request failed, bad header", NULL); + kd_free(rkd); + return false; + } - *dp = 0; - rkd[i].key = strdup(line); - rkd[i].data = strdup(ltrim(dp + 1)); + *dp = 0; + rkd[i].key = strdup(line); + rkd[i].data = strdup(ltrim(dp + 1)); - if (!strcasecmp(rkd[i].key, "Content-Length")) *len = atol(rkd[i].data); + if(!strcasecmp(rkd[i].key, "Content-Length")) *len = atol(rkd[i].data); - i++; - rkd[i].key = NULL; - } + i++; + rkd[i].key = NULL; + } - if (*len) { - int size = 0; + if(*len) { + int size = 0; - *body = malloc(*len + 1); - while (*body && size < *len) { - int bytes = recv(sock, *body + size, *len - size, 0); - if (bytes <= 0) break; - size += bytes; - } + *body = malloc(*len + 1); + while(*body && size < *len) { + int bytes = recv(sock, *body + size, *len - size, 0); + if(bytes <= 0) break; + size += bytes; + } - (*body)[*len] = '\0'; + (*body)[*len] = '\0'; - if (!*body || size != *len) { - LOG_ERROR("content length receive error %d %d", *len, size); - } - } + if(!*body || size != *len) { LOG_ERROR("content length receive error %d %d", *len, size); } + } - return true; + return true; } - /*----------------------------------------------------------------------------*/ -static int read_line(int fd, char *line, int maxlen, int timeout) -{ - int i,rval; - int count=0; - struct pollfd pfds; - char ch; +static int read_line(int fd, char* line, int maxlen, int timeout) { + int i, rval; + int count = 0; + struct pollfd pfds; + char ch; - *line = 0; - pfds.fd = fd; - pfds.events = POLLIN; + *line = 0; + pfds.fd = fd; + pfds.events = POLLIN; - for(i = 0; i < maxlen; i++){ - if (poll(&pfds, 1, timeout)) rval=recv(fd, &ch, 1, 0); - else return 0; + for(i = 0; i < maxlen; i++) { + if(poll(&pfds, 1, timeout)) + rval = recv(fd, &ch, 1, 0); + else + return 0; - if (rval == -1) { - if (errno == EAGAIN) return 0; - LOG_ERROR("fd: %d read error: %s", fd, strerror(errno)); - return -1; - } + if(rval == -1) { + if(errno == EAGAIN) return 0; + LOG_ERROR("fd: %d read error: %s", fd, strerror(errno)); + return -1; + } - if (rval == 0) { - LOG_INFO("disconnected on the other end %u", fd); - return 0; - } + if(rval == 0) { + LOG_INFO("disconnected on the other end %u", fd); + return 0; + } - if (ch == '\n') { - *line=0; - return count; - } + if(ch == '\n') { + *line = 0; + return count; + } - if (ch=='\r') continue; + if(ch == '\r') continue; - *line++=ch; - count++; - if (count >= maxlen-1) break; - } + *line++ = ch; + count++; + if(count >= maxlen - 1) break; + } - *line = 0; - return count; + *line = 0; + return count; } - /*----------------------------------------------------------------------------*/ -char *http_send(int sock, char *method, key_data_t *rkd) -{ - unsigned sent, len; - char *resp = kd_dump(rkd); - char *data = malloc(strlen(method) + 2 + strlen(resp) + 2 + 1); +char* http_send(int sock, char* method, key_data_t* rkd) { + unsigned sent, len; + char* resp = kd_dump(rkd); + char* data = malloc(strlen(method) + 2 + strlen(resp) + 2 + 1); - len = sprintf(data, "%s\r\n%s\r\n", method, resp); - NFREE(resp); + len = sprintf(data, "%s\r\n%s\r\n", method, resp); + NFREE(resp); - sent = send(sock, data, len, 0); + sent = send(sock, data, len, 0); - if (sent != len) { - LOG_ERROR("HTTP send() error:%s %u (strlen=%u)", data, sent, len); - NFREE(data); - } + if(sent != len) { + LOG_ERROR("HTTP send() error:%s %u (strlen=%u)", data, sent, len); + NFREE(data); + } - return data; + return data; } - /*----------------------------------------------------------------------------*/ -char *kd_lookup(key_data_t *kd, char *key) -{ - int i = 0; - while (kd && kd[i].key){ - if (!strcasecmp(kd[i].key, key)) return kd[i].data; - i++; - } - return NULL; +char* kd_lookup(key_data_t* kd, char* key) { + int i = 0; + while(kd && kd[i].key) { + if(!strcasecmp(kd[i].key, key)) return kd[i].data; + i++; + } + return NULL; } - /*----------------------------------------------------------------------------*/ -bool kd_add(key_data_t *kd, char *key, char *data) -{ - int i = 0; - while (kd && kd[i].key) i++; +bool kd_add(key_data_t* kd, char* key, char* data) { + int i = 0; + while(kd && kd[i].key) i++; - kd[i].key = strdup(key); - kd[i].data = strdup(data); - kd[i+1].key = NULL; + kd[i].key = strdup(key); + kd[i].data = strdup(data); + kd[i + 1].key = NULL; - return NULL; + return NULL; } - /*----------------------------------------------------------------------------*/ -void kd_free(key_data_t *kd) -{ - int i = 0; - while (kd && kd[i].key){ - free(kd[i].key); - if (kd[i].data) free(kd[i].data); - i++; - } +void kd_free(key_data_t* kd) { + int i = 0; + while(kd && kd[i].key) { + free(kd[i].key); + if(kd[i].data) free(kd[i].data); + i++; + } - kd[0].key = NULL; + kd[0].key = NULL; } - /*----------------------------------------------------------------------------*/ -char *kd_dump(key_data_t *kd) -{ - int i = 0; - int pos = 0, size = 0; - char *str = NULL; +char* kd_dump(key_data_t* kd) { + int i = 0; + int pos = 0, size = 0; + char* str = NULL; - if (!kd || !kd[0].key) return strdup("\r\n"); + if(!kd || !kd[0].key) return strdup("\r\n"); - while (kd && kd[i].key) { - char *buf; - int len; + while(kd && kd[i].key) { + char* buf; + int len; - len = asprintf(&buf, "%s: %s\r\n", kd[i].key, kd[i].data); + len = asprintf(&buf, "%s: %s\r\n", kd[i].key, kd[i].data); - while (pos + len >= size) { - void *p = realloc(str, size + 1024); - size += 1024; - if (!p) { - free(str); - return NULL; - } - str = p; - } + while(pos + len >= size) { + void* p = realloc(str, size + 1024); + size += 1024; + if(!p) { + free(str); + return NULL; + } + str = p; + } - memcpy(str + pos, buf, len); + memcpy(str + pos, buf, len); - pos += len; - free(buf); - i++; - } + pos += len; + free(buf); + i++; + } - str[pos] = '\0'; + str[pos] = '\0'; - return str; + return str; } /*--------------------------------------------------------------------------*/ -void free_metadata(struct metadata_s *metadata) -{ - NFREE(metadata->artist); - NFREE(metadata->album); - NFREE(metadata->title); - NFREE(metadata->genre); - NFREE(metadata->path); - NFREE(metadata->artwork); - NFREE(metadata->remote_title); +void free_metadata(struct metadata_s* metadata) { + NFREE(metadata->artist); + NFREE(metadata->album); + NFREE(metadata->title); + NFREE(metadata->genre); + NFREE(metadata->path); + NFREE(metadata->artwork); + NFREE(metadata->remote_title); } - /*----------------------------------------------------------------------------*/ -int _fprintf(FILE *file, ...) -{ - va_list args; - char *fmt; - int n; +int _fprintf(FILE* file, ...) { + va_list args; + char* fmt; + int n; - va_start(args, file); - fmt = va_arg(args, char*); + va_start(args, file); + fmt = va_arg(args, char*); - n = vfprintf(file, fmt, args); - va_end(args); - return n; + n = vfprintf(file, fmt, args); + va_end(args); + return n; } - - - - - - - - diff --git a/components/raop/util.h b/components/raop/util.h index 75016521..02969344 100644 --- a/components/raop/util.h +++ b/components/raop/util.h @@ -23,67 +23,75 @@ #include "freertos/timers.h" #endif -#define NFREE(p) if (p) { free(p); p = NULL; } +#define NFREE(p) \ + if(p) { \ + free(p); \ + p = NULL; \ + } typedef struct metadata_s { - char *artist; - char *album; - char *title; - char *genre; - char *path; - char *artwork; - char *remote_title; - u32_t track; - u32_t duration; - u32_t track_hash; - u32_t sample_rate; - u8_t sample_size; - u8_t channels; + char* artist; + char* album; + char* title; + char* genre; + char* path; + char* artwork; + char* remote_title; + u32_t track; + u32_t duration; + u32_t track_hash; + u32_t sample_rate; + u8_t sample_size; + u8_t channels; } metadata_t; -void free_metadata(struct metadata_s *metadata); -void dup_metadata(struct metadata_s *dst, struct metadata_s *src); - u32_t gettime_ms(void); +void free_metadata(struct metadata_s* metadata); +void dup_metadata(struct metadata_s* dst, struct metadata_s* src); + +u32_t gettime_ms(void); #ifdef WIN32 -char* strsep(char** stringp, const char* delim); -char *strndup(const char *s, size_t n); -int asprintf(char **strp, const char *fmt, ...); -void winsock_init(void); -void winsock_close(void); -#define SAFE_PTR_FREE(P) free(P) #else -char *strlwr(char *str); +char* strsep(char** stringp, const char* delim); +char* strndup(const char* s, size_t n); +int asprintf(char** strp, const char* fmt, ...); +void winsock_init(void); +void winsock_close(void); +#define SAFE_PTR_FREE(P) free(P) +#else +char* strlwr(char* str); // reason is that TCB might be cleanup in idle task -#define SAFE_PTR_FREE(P) \ - do { \ - TimerHandle_t timer = xTimerCreate("cleanup", pdMS_TO_TICKS(10000), pdFALSE, P, _delayed_free); \ - xTimerStart(timer, portMAX_DELAY); \ - } while (0) +#define SAFE_PTR_FREE(P) \ + do { \ + TimerHandle_t timer = xTimerCreate("cleanup", pdMS_TO_TICKS(10000), pdFALSE, P, _delayed_free); \ + xTimerStart(timer, portMAX_DELAY); \ + } while(0) static void inline _delayed_free(TimerHandle_t xTimer) { - free(pvTimerGetTimerID(xTimer)); - xTimerDelete(xTimer, portMAX_DELAY); -} + free(pvTimerGetTimerID(xTimer)); + xTimerDelete(xTimer, portMAX_DELAY); +} #endif -char* strextract(char *s1, char *beg, char *end); -in_addr_t get_localhost(char **name); -void get_mac(u8_t mac[]); -int shutdown_socket(int sd); -int bind_socket(short unsigned *port, int mode); -int conn_socket(unsigned short port); typedef struct { - char *key; - char *data; +char* strextract(char* s1, char* beg, char* end); +in_addr_t get_localhost(char** name); +void get_mac(u8_t mac[]); +int shutdown_socket(int sd); +int bind_socket(short unsigned* port, int mode); +int conn_socket(unsigned short port); +typedef struct { + + char* key; + char* data; } key_data_t; -bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len); char* http_send(int sock, char *method, key_data_t *rkd); +bool http_parse(int sock, char* method, key_data_t* rkd, char** body, int* len); +char* http_send(int sock, char* method, key_data_t* rkd); -char* kd_lookup(key_data_t *kd, char *key); -bool kd_add(key_data_t *kd, char *key, char *value); -char* kd_dump(key_data_t *kd); -void kd_free(key_data_t *kd); +char* kd_lookup(key_data_t* kd, char* key); +bool kd_add(key_data_t* kd, char* key, char* value); +char* kd_dump(key_data_t* kd); +void kd_free(key_data_t* kd); -int _fprintf(FILE *file, ...); +int _fprintf(FILE* file, ...); #endif - diff --git a/components/services/accessors.c b/components/services/accessors.c index 055d105a..cf671647 100644 --- a/components/services/accessors.c +++ b/components/services/accessors.c @@ -26,7 +26,7 @@ #include "sdkconfig.h" #include "soc/efuse_periph.h" #include "driver/gpio.h" -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/efuse.h" #endif #include "tools.h" @@ -34,27 +34,26 @@ #include "messaging.h" #include "network_ethernet.h" -static const char *TAG = "services"; -const char *i2c_name_type="I2C"; -const char *spi_name_type="SPI"; -cJSON * gpio_list=NULL; -#define min(a,b) (((a) < (b)) ? (a) : (b)) +static const char* TAG = "services"; +const char* i2c_name_type = "I2C"; +const char* spi_name_type = "SPI"; +cJSON* gpio_list = NULL; +#define min(a, b) (((a) < (b)) ? (a) : (b)) #ifndef QUOTE - #define QUOTE(name) #name +#define QUOTE(name) #name #endif #ifndef STR - #define STR(macro) QUOTE(macro) +#define STR(macro) QUOTE(macro) #endif -extern cJSON * get_gpio_list(bool refresh); -bool are_statistics_enabled(){ -#if defined(CONFIG_FREERTOS_USE_TRACE_FACILITY) && defined (CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS) - return true; +extern cJSON* get_gpio_list(bool refresh); +bool are_statistics_enabled() { +#if defined(CONFIG_FREERTOS_USE_TRACE_FACILITY) && defined(CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS) + return true; #endif - return false; + return false; } - /**************************************************************************************** * */ @@ -78,24 +77,20 @@ bool are_statistics_enabled(){ /**************************************************************************************** * */ -bool is_dac_config_locked(){ -#if ( defined CONFIG_DAC_CONFIG ) - if(strlen(CONFIG_DAC_CONFIG) > 0){ - return true; - } +bool is_dac_config_locked() { +#if(defined CONFIG_DAC_CONFIG) + if(strlen(CONFIG_DAC_CONFIG) > 0) { return true; } #endif -#if defined(CONFIG_I2S_BCK_IO) && CONFIG_I2S_BCK_IO>0 - return true; +#if defined(CONFIG_I2S_BCK_IO) && CONFIG_I2S_BCK_IO > 0 + return true; #endif - return false; + return false; } - -const sys_i2c_bus* get_i2c_bus(i2c_port_t port){ - if(platform->dev.has_i2c && port == platform->dev.i2c.port-sys_i2c_port_PORT0 && platform->dev.i2c.scl>=0){ - return &platform->dev.i2c; - } - if(platform->dev.has_dac && platform->dev.dac.has_i2c && (platform->dev.dac.i2c.port - sys_i2c_port_PORT0) == port && platform->dev.dac.i2c.scl>=0){ +const sys_i2c_bus* get_i2c_bus(i2c_port_t port) { + if(platform->dev.has_i2c && port == platform->dev.i2c.port - sys_i2c_port_PORT0 && platform->dev.i2c.scl >= 0) { return &platform->dev.i2c; } + if(platform->dev.has_dac && platform->dev.dac.has_i2c && (platform->dev.dac.i2c.port - sys_i2c_port_PORT0) == port && + platform->dev.dac.i2c.scl >= 0) { return &platform->dev.dac.i2c; } return NULL; @@ -103,80 +98,64 @@ const sys_i2c_bus* get_i2c_bus(i2c_port_t port){ /**************************************************************************************** * */ -const i2c_config_t * config_i2c_get(sys_i2c_bus * bus) { - - static i2c_config_t i2c = { - .mode = I2C_MODE_MASTER, - .sda_io_num = -1, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_io_num = -1, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = 0, - }; +const i2c_config_t* config_i2c_get(sys_i2c_bus* bus) { - if(bus && bus->scl >=0 && bus->sda >=0 ){ - if(bus->scl>=0){ - i2c.scl_io_num = bus->scl; - } - else { - ESP_LOGE(TAG,"%s missing for i2c","SCL"); - } - - if(bus->sda>=0){ - i2c.sda_io_num= bus->sda; - } - else { - ESP_LOGE(TAG,"%s missing for i2c","SDA"); - } - if(bus->speed>0){ - i2c.master.clk_speed = bus->speed; - } - } + static i2c_config_t i2c = { + .mode = I2C_MODE_MASTER, + .sda_io_num = -1, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_io_num = -1, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 0, + }; - return &i2c; + if(bus && bus->scl >= 0 && bus->sda >= 0) { + if(bus->scl >= 0) { + i2c.scl_io_num = bus->scl; + } else { + ESP_LOGE(TAG, "%s missing for i2c", "SCL"); + } + + if(bus->sda >= 0) { + i2c.sda_io_num = bus->sda; + } else { + ESP_LOGE(TAG, "%s missing for i2c", "SDA"); + } + if(bus->speed > 0) { i2c.master.clk_speed = bus->speed; } + } + + return &i2c; } - -void config_set_gpio(int * pin, sys_gpio_config * gpio,bool has_value, const char * name, bool mandatory){ - if(has_value){ - ESP_LOGD(TAG, "Setting pin %d as %s", gpio->pin, name); - if(pin) *pin= gpio->pin; - } - else if(mandatory) { - ESP_LOGE(TAG,"Pin %s has no value",name); - } - else { - ESP_LOGD(TAG,"Pin %s has no value",name); - } +void config_set_gpio(int* pin, sys_gpio_config* gpio, bool has_value, const char* name, bool mandatory) { + if(has_value) { + ESP_LOGD(TAG, "Setting pin %d as %s", gpio->pin, name); + if(pin) *pin = gpio->pin; + } else if(mandatory) { + ESP_LOGE(TAG, "Pin %s has no value", name); + } else { + ESP_LOGD(TAG, "Pin %s has no value", name); + } } /**************************************************************************************** * */ -const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) { - // don't memset all to 0xff as it's more than just GPIO - static spi_bus_config_t spi = { - .mosi_io_num = -1, - .sclk_io_num = -1, - .miso_io_num = -1, - .quadwp_io_num = -1, - .quadhd_io_num = -1 - }; - if(platform->has_dev && platform->dev.has_spi){ - ESP_LOGD(TAG,"SPI Configuration found"); - spi.mosi_io_num = platform->dev.spi.mosi; - spi.miso_io_num = platform->dev.spi.miso; - spi.sclk_io_num = platform->dev.spi.clk; - spi_system_dc_gpio = platform->dev.spi.dc; - // only VSPI (1) can be used as Flash and PSRAM run at 80MHz - if(platform->dev.spi.host!=sys_dev_common_hosts_NONE){ - spi_system_host = platform->dev.spi.host-sys_dev_common_hosts_Host0; - } - } - else { - ESP_LOGI(TAG,"SPI not configured"); - } - - if(spi_host) *spi_host = spi_system_host; - return &spi; +const spi_bus_config_t* config_spi_get(spi_host_device_t* spi_host) { + // don't memset all to 0xff as it's more than just GPIO + static spi_bus_config_t spi = {.mosi_io_num = -1, .sclk_io_num = -1, .miso_io_num = -1, .quadwp_io_num = -1, .quadhd_io_num = -1}; + if(platform->has_dev && platform->dev.has_spi) { + ESP_LOGD(TAG, "SPI Configuration found"); + spi.mosi_io_num = platform->dev.spi.mosi; + spi.miso_io_num = platform->dev.spi.miso; + spi.sclk_io_num = platform->dev.spi.clk; + spi_system_dc_gpio = platform->dev.spi.dc; + // only VSPI (1) can be used as Flash and PSRAM run at 80MHz + if(platform->dev.spi.host != sys_dev_common_hosts_NONE) { spi_system_host = platform->dev.spi.host - sys_dev_common_hosts_Host0; } + } else { + ESP_LOGI(TAG, "SPI not configured"); + } + + if(spi_host) *spi_host = spi_system_host; + return &spi; } diff --git a/components/services/accessors.h b/components/services/accessors.h index 0518a9cd..748dfe42 100644 --- a/components/services/accessors.h +++ b/components/services/accessors.h @@ -16,52 +16,55 @@ #include "I2CBus.pb.h" #define ASSIGN_GPIO(pin, root, name, mandatory) config_set_gpio(&pin, &(root).name, (root).has_##name, #name, mandatory) -#define ASSIGN_COND_VAL_1LVL(name, targetval) \ - ((targetval) = (platform && platform->has_##name ? &(platform->name) : NULL)) -#define ASSIGN_COND_VAL_2LVL(name1, name2, targetval) \ +#define ASSIGN_COND_VAL_1LVL(name, targetval) ((targetval) = (platform && platform->has_##name ? &(platform->name) : NULL)) +#define ASSIGN_COND_VAL_2LVL(name1, name2, targetval) \ ((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 ? &(platform->name1.name2) : NULL)) -#define ASSIGN_COND_VAL_3LVL(name1, name2, name3, targetval) \ - ((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 ? &(platform->name1.name2.name3) : NULL)) -#define ASSIGN_COND_VAL_4LVL(name1, name2, name3, name4, targetval) \ - ((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 && platform->name1.name2.name3.has_##name4 ? &(platform->name1.name2.name3.name4) : NULL)) -#define ASSIGN_COND_VAL_5LVL(name1, name2, name3, name4, name5, targetval) \ - ((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 && platform->name1.name2.name3.has_##name4 && platform->name1.name2.name3.name4.has_##name5 ? &(platform->name1.name2.name3.name4.name5) : NULL)) +#define ASSIGN_COND_VAL_3LVL(name1, name2, name3, targetval) \ + ((targetval) = \ + (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 ? &(platform->name1.name2.name3) \ + : NULL)) +#define ASSIGN_COND_VAL_4LVL(name1, name2, name3, name4, targetval) \ + ((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 && \ + platform->name1.name2.name3.has_##name4 \ + ? &(platform->name1.name2.name3.name4) \ + : NULL)) +#define ASSIGN_COND_VAL_5LVL(name1, name2, name3, name4, name5, targetval) \ + ((targetval) = (platform && platform->has_##name1 && platform->name1.has_##name2 && platform->name1.name2.has_##name3 && \ + platform->name1.name2.name3.has_##name4 && platform->name1.name2.name3.name4.has_##name5 \ + ? &(platform->name1.name2.name3.name4.name5) \ + : NULL)) +#define SYS_NET(target) ASSIGN_COND_VAL_1LVL(net, target) +#define SYS_DISPLAY(target) ASSIGN_COND_VAL_2LVL(dev, display, target) +#define SYS_DEV_LEDSTRIP(target) ASSIGN_COND_VAL_2LVL(dev, led_strip, target) +#define SYS_DEV(target) ASSIGN_COND_VAL_1LVL(dev, target) +#define SYS_DEV_ROTARY(target) ASSIGN_COND_VAL_2LVL(dev, rotary, target) +#define SYS_DEV_IR(target) ASSIGN_COND_VAL_2LVL(dev, ir, target) +#define SYS_DISPLAY_COMMON(target) ASSIGN_COND_VAL_3LVL(dev, display, common, target) +#define SYS_DISPLAY_SPI(target) ASSIGN_COND_VAL_3LVL(dev, display, spi, target) +#define SYS_DISPLAY_I2C(target) ASSIGN_COND_VAL_3LVL(dev, display, i2c, target) +#define SYS_GPIOS(target) ASSIGN_COND_VAL_2LVL(dev, gpios, target) +#define SYS_ETH(target) ASSIGN_COND_VAL_2LVL(dev, eth, target) +#define SYS_ETH_COMMON(target) ASSIGN_COND_VAL_3LVL(dev, eth, common, target) +#define sys_i2c_bus(target) ASSIGN_COND_VAL_2LVL(dev, i2c, target) +#define SYS_GPIOS_NAME(name, target) ASSIGN_COND_VAL_2LVL(gpios, name, target) +#define sys_services_config(target) ASSIGN_COND_VAL_1LVL(services, target) +#define sys_services_config_SPOTIFY(target) ASSIGN_COND_VAL_2LVL(services, cspot, target) +#define sys_services_config_METADATA(target) ASSIGN_COND_VAL_2LVL(services, metadata, target) +#define sys_services_config_AIRPLAY(target) ASSIGN_COND_VAL_2LVL(services, airplay, target) +#define sys_services_config_SLEEP(target) ASSIGN_COND_VAL_2LVL(services, sleep, target) +#define sys_services_config_EQUALIZER(target) ASSIGN_COND_VAL_2LVL(services, equalizer, target) -#define SYS_NET(target) ASSIGN_COND_VAL_1LVL(net,target) -#define SYS_DISPLAY(target) ASSIGN_COND_VAL_2LVL(dev,display,target) -#define SYS_DEV_LEDSTRIP(target) ASSIGN_COND_VAL_2LVL(dev,led_strip,target) -#define SYS_DEV(target) ASSIGN_COND_VAL_1LVL(dev,target) -#define SYS_DEV_ROTARY(target) ASSIGN_COND_VAL_2LVL(dev,rotary,target) -#define SYS_DEV_IR(target) ASSIGN_COND_VAL_2LVL(dev,ir,target) -#define SYS_DISPLAY_COMMON(target) ASSIGN_COND_VAL_3LVL(dev,display,common,target) -#define SYS_DISPLAY_SPI(target) ASSIGN_COND_VAL_3LVL(dev,display,spi,target) -#define SYS_DISPLAY_I2C(target) ASSIGN_COND_VAL_3LVL(dev,display,i2c,target) -#define SYS_GPIOS(target) ASSIGN_COND_VAL_2LVL(dev,gpios,target) -#define SYS_ETH(target) ASSIGN_COND_VAL_2LVL(dev,eth,target) -#define SYS_ETH_COMMON(target) ASSIGN_COND_VAL_3LVL(dev,eth,common,target) +#define sys_services_config_TELNET(target) ASSIGN_COND_VAL_2LVL(services, telnet, target) +#define sys_services_config_BTSINK(target) ASSIGN_COND_VAL_2LVL(services, bt_sink, target) +#define SYS_DEV_BATTERY(target) ASSIGN_COND_VAL_2LVL(dev, battery, target) -#define sys_i2c_bus(target) ASSIGN_COND_VAL_2LVL(dev,i2c,target) -#define SYS_GPIOS_NAME(name,target) ASSIGN_COND_VAL_2LVL(gpios,name,target) -#define sys_services_config(target) ASSIGN_COND_VAL_1LVL(services,target) -#define sys_services_config_SPOTIFY(target) ASSIGN_COND_VAL_2LVL(services,cspot,target) -#define sys_services_config_METADATA(target) ASSIGN_COND_VAL_2LVL(services,metadata,target) -#define sys_services_config_AIRPLAY(target) ASSIGN_COND_VAL_2LVL(services,airplay,target) -#define sys_services_config_SLEEP(target) ASSIGN_COND_VAL_2LVL(services,sleep,target) -#define sys_services_config_EQUALIZER(target) ASSIGN_COND_VAL_2LVL(services,equalizer,target) +const i2c_config_t* config_i2c_get(sys_i2c_bus* bus); +const spi_bus_config_t* config_spi_get(spi_host_device_t* spi_host); +const gpio_exp_config_t* config_gpio_exp_get(int index); +const sys_i2c_bus* get_i2c_bus(i2c_port_t port); -#define sys_services_config_TELNET(target) ASSIGN_COND_VAL_2LVL(services,telnet,target) -#define sys_services_config_BTSINK(target) ASSIGN_COND_VAL_2LVL(services,bt_sink,target) - - -#define SYS_DEV_BATTERY(target) ASSIGN_COND_VAL_2LVL(dev,battery,target) - -const i2c_config_t * config_i2c_get(sys_i2c_bus * bus); -const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host); -const gpio_exp_config_t * config_gpio_exp_get(int index); -const sys_i2c_bus* get_i2c_bus(i2c_port_t port); - -bool is_dac_config_locked(); -bool are_statistics_enabled(); +bool is_dac_config_locked(); +bool are_statistics_enabled(); diff --git a/components/services/audio_controls.c b/components/services/audio_controls.c index 1a38fd45..5f8d8c0b 100644 --- a/components/services/audio_controls.c +++ b/components/services/audio_controls.c @@ -78,10 +78,9 @@ bool actrls_ir_action(uint16_t addr, uint16_t cmd) { uint32_t code = (addr << 16) | cmd; struct ir_action_map_s const* map = ir_action_map; - while (map->code && map->code != code) - map++; + while(map->code && map->code != code) map++; - if (map->code && current_controls[map->action]) { + if(map->code && current_controls[map->action]) { current_controls[map->action](true); return true; } else { @@ -94,7 +93,7 @@ bool actrls_ir_action(uint16_t addr, uint16_t cmd) { */ static void ir_handler(uint16_t addr, uint16_t cmd) { ESP_LOGD(TAG, "recaived IR %04hx:%04hx", addr, cmd); - if (current_ir_handler) current_ir_handler(addr, cmd); + if(current_ir_handler) current_ir_handler(addr, cmd); } /**************************************************************************************** @@ -104,7 +103,7 @@ esp_err_t actrls_init(const char* profile_name) { esp_err_t err = ESP_OK; sys_dev_ir* ir = NULL; sys_btns_rotary* dev_config = NULL; - if (!SYS_DEV_ROTARY(dev_config)) { + if(!SYS_DEV_ROTARY(dev_config)) { ESP_LOGD(TAG, "Rotary not configured"); return ESP_OK; } @@ -114,8 +113,8 @@ esp_err_t actrls_init(const char* profile_name) { A = dev_config->A; B = dev_config->B; SW = dev_config->SW; - if (A >= 0 && B >= 0) { - if (dev_config->has_knobonly && dev_config->knobonly.enable) { + if(A >= 0 && B >= 0) { + if(dev_config->has_knobonly && dev_config->knobonly.enable) { p = strchr(p, '='); int double_press = dev_config->knobonly.delay_ms > 0 ? dev_config->knobonly.delay_ms : 350; @@ -124,8 +123,8 @@ esp_err_t actrls_init(const char* profile_name) { ESP_LOGI(TAG, "single knob navigation %d", double_press); } else { - if (dev_config->volume) rotary.volume_lock = true; - if (dev_config->longpress) longpress = 1000; + if(dev_config->volume) rotary.volume_lock = true; + if(dev_config->longpress) longpress = 1000; } // create rotary (no handling of long press) @@ -134,15 +133,15 @@ esp_err_t actrls_init(const char* profile_name) { ESP_LOGI(TAG, "Rotary control not configured."); } - if (SYS_DEV_IR(ir) && ir->gpio >= 0 && ir->type != sys_dev_ir_types_IR_UNKNOWN) { + if(SYS_DEV_IR(ir) && ir->gpio >= 0 && ir->type != sys_dev_ir_types_IR_UNKNOWN) { ESP_LOGD(TAG, "Infrared config found on pin %d, protocol: %s", ir->gpio, sys_dev_ir_types_name(ir->type)); - if (ir->type == sys_dev_ir_types_IR_NEC) { + if(ir->type == sys_dev_ir_types_IR_NEC) { create_infrared(ir->gpio, ir_handler, IR_RC5); } else { create_infrared(ir->gpio, ir_handler, IR_NEC); } } - if (!err) + if(!err) return actrls_init_profile(profile_name, true); else return err; @@ -153,9 +152,7 @@ esp_err_t actrls_init(const char* profile_name) { * */ static const char* get_action_desc(sys_btns_action* action_detail) { - if (action_detail->type != sys_btns_actions_REMAP) { - return sys_btns_actions_name(action_detail->type); - } + if(action_detail->type != sys_btns_actions_REMAP) { return sys_btns_actions_name(action_detail->type); } return STR_OR_ALT(action_detail->profile_name, ""); } @@ -167,15 +164,15 @@ static void control_handler(void* client, button_event_e event, button_press_e p sys_btns_action* action_detail; static sys_btns_action actionNone = sys_btns_action_init_default; - switch (press) { + switch(press) { case BUTTON_NORMAL: - if (long_press) + if(long_press) action_detail = (event == BUTTON_PRESSED ? &key->longpress.pressed : &key->longpress.released); else action_detail = (event == BUTTON_PRESSED ? &key->normal.pressed : &key->normal.released); break; case BUTTON_SHIFTED: - if (long_press) + if(long_press) action_detail = (event == BUTTON_PRESSED ? &key->longshifted.pressed : &key->longshifted.released); else action_detail = (event == BUTTON_PRESSED ? &key->shifted.pressed : &key->shifted.released); @@ -188,27 +185,27 @@ static void control_handler(void* client, button_event_e event, button_press_e p ESP_LOGD(TAG, "control gpio:%u press:%u long:%u event:%u action:%s", key->gpio, press, long_press, event, get_action_desc(action_detail)); // stop here if control hook served the request - if (current_hook && (*current_hook)(key->gpio, action_detail, event, press, long_press)) return; + if(current_hook && (*current_hook)(key->gpio, action_detail, event, press, long_press)) return; // in raw mode, we just do normal action press *and* release, there is no longpress nor shift - if (current_raw_controls && action_detail->type != sys_btns_actions_A_SLEEP) { + if(current_raw_controls && action_detail->type != sys_btns_actions_A_SLEEP) { sys_btns_actions action = key->normal.has_pressed && key->normal.pressed.type != sys_btns_actions_A_NONE ? key->normal.pressed.type : key->normal.released.type; ESP_LOGD(TAG, "calling action %s in raw mode", sys_btns_actions_name(action)); - if (action != sys_btns_actions_A_NONE && current_controls[action]) current_controls[action](event == BUTTON_PRESSED); + if(action != sys_btns_actions_A_NONE && current_controls[action]) current_controls[action](event == BUTTON_PRESSED); return; } // otherwise process using configuration - if (action_detail->type == sys_btns_actions_REMAP) { + if(action_detail->type == sys_btns_actions_REMAP) { // remap requested ESP_LOGD(TAG, "remapping buttons to profile %s", action_detail->profile_name); cJSON* profile_obj = cJSON_GetObjectItem(control_profiles, action_detail->profile_name); - if (profile_obj) { + if(profile_obj) { actrls_config_t* cur_config = (actrls_config_t*)cJSON_GetStringValue(profile_obj); - if (cur_config) { + if(cur_config) { ESP_LOGD(TAG, "Remapping all the buttons that are found in the new profile"); - while (cur_config->gpio != -1) { + while(cur_config->gpio != -1) { ESP_LOGD(TAG, "Remapping button with gpio %u", cur_config->gpio); button_remap((void*)cur_config, cur_config->gpio, control_handler, cur_config->long_press, cur_config->shifter_gpio); cur_config++; @@ -219,12 +216,12 @@ static void control_handler(void* client, button_event_e event, button_press_e p } else { ESP_LOGE(TAG, "Invalid profile name %s. Cannot remap buttons", action_detail->profile_name); } - } else if (action_detail->type == sys_btns_actions_A_SLEEP) { + } else if(action_detail->type == sys_btns_actions_A_SLEEP) { ESP_LOGI(TAG, "special sleep button pressed"); services_sleep_activate(SLEEP_ONKEY); - } else if (action_detail->type != sys_btns_actions_A_NONE) { + } else if(action_detail->type != sys_btns_actions_A_NONE) { ESP_LOGD(TAG, "calling action %s", sys_btns_actions_name(action_detail->type)); - if (current_controls[action_detail->type]) (*current_controls[action_detail->type])(event == BUTTON_PRESSED); + if(current_controls[action_detail->type]) (*current_controls[action_detail->type])(event == BUTTON_PRESSED); } } @@ -236,61 +233,61 @@ static void control_rotary_handler(void* client, rotary_event_e event, bool long bool pressed = true; // in raw mode, we just pass rotary events - if (current_raw_controls) { - if (event == ROTARY_LEFT) + if(current_raw_controls) { + if(event == ROTARY_LEFT) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); - else if (event == ROTARY_RIGHT) + else if(event == ROTARY_RIGHT) (*current_controls[sys_btns_actions_KNOB_RIGHT])(true); else (*current_controls[sys_btns_actions_KNOB_PUSH])(event == ROTARY_PRESSED); return; } - switch (event) { + switch(event) { case ROTARY_LEFT: - if (rotary.timer) { - if (rotary.left_count) { + if(rotary.timer) { + if(rotary.left_count) { action = sys_btns_actions_KNOB_LEFT; // need to add a left button the first time - if (rotary.left_count == 1) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); + if(rotary.left_count == 1) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); } xTimerStart(rotary.timer, 20 / portTICK_PERIOD_MS); rotary.left_count++; - } else if (rotary.long_state) + } else if(rotary.long_state) action = sys_btns_actions_A_PREV; - else if (rotary.volume_lock) + else if(rotary.volume_lock) action = sys_btns_actions_A_VOLDOWN; else action = sys_btns_actions_KNOB_LEFT; break; case ROTARY_RIGHT: - if (rotary.timer) { - if (rotary.left_count == 1) { + if(rotary.timer) { + if(rotary.left_count == 1) { action = sys_btns_actions_A_PAUSE; rotary.left_count = 0; xTimerStop(rotary.timer, 0); } else action = sys_btns_actions_KNOB_RIGHT; - } else if (rotary.long_state) + } else if(rotary.long_state) action = sys_btns_actions_A_NEXT; - else if (rotary.volume_lock) + else if(rotary.volume_lock) action = sys_btns_actions_A_VOLUP; else action = sys_btns_actions_KNOB_RIGHT; break; case ROTARY_PRESSED: - if (rotary.timer) { - if (long_press) + if(rotary.timer) { + if(long_press) action = sys_btns_actions_A_PLAY; - else if (rotary.click_pending) { + else if(rotary.click_pending) { action = sys_btns_actions_B_LEFT; xTimerStop(rotary.timer, 0); } else xTimerStart(rotary.timer, 20 / portTICK_PERIOD_MS); rotary.click_pending = !rotary.click_pending; - } else if (long_press) + } else if(long_press) rotary.long_state = !rotary.long_state; - else if (rotary.volume_lock) + else if(rotary.volume_lock) action = sys_btns_actions_A_TOGGLE; else action = sys_btns_actions_KNOB_PUSH; @@ -299,18 +296,18 @@ static void control_rotary_handler(void* client, rotary_event_e event, bool long break; } - if (action != sys_btns_actions_A_NONE) (*current_controls[action])(pressed); + if(action != sys_btns_actions_A_NONE) (*current_controls[action])(pressed); } /**************************************************************************************** * */ static void rotary_timer(TimerHandle_t xTimer) { - if (rotary.click_pending) { + if(rotary.click_pending) { (*current_controls[sys_btns_actions_KNOB_PUSH])(true); rotary.click_pending = false; - } else if (rotary.left_count) { - if (rotary.left_count == 1) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); + } else if(rotary.left_count) { + if(rotary.left_count == 1) (*current_controls[sys_btns_actions_KNOB_LEFT])(true); rotary.left_count = 0; } } @@ -323,7 +320,7 @@ static void actrls_parse_action(const char* name) { ESP_LOGD(TAG, "unknown action %s, trying to find matching profile ", name); cJSON* existing = cJSON_GetObjectItem(control_profiles, name); - if (!existing) { + if(!existing) { ESP_LOGD(TAG, "Loading new audio control profile with name: %s", name); actrls_init_profile(name, false); } else { @@ -337,16 +334,16 @@ static void actrls_parse_action(const char* name) { static esp_err_t actrls_process_action(const sys_btns_action* action, sys_btns_action* cur_config_act) { bool valid_name = action->profile_name && strlen(action->profile_name) > 0; cur_config_act->type = action->type; - if (valid_name) { + if(valid_name) { cur_config_act->profile_name = strdup_psram(action->profile_name); - if (!cur_config_act->profile_name) { + if(!cur_config_act->profile_name) { ESP_LOGE(TAG, "Error allocating memory for action profile name %s", action->profile_name); return ESP_ERR_NO_MEM; } } - if (action->type == sys_btns_actions_REMAP) { - if (!valid_name) { + if(action->type == sys_btns_actions_REMAP) { + if(!valid_name) { ESP_LOGE(TAG, "Missing name for action %s", sys_btns_actions_name(action->type)); return ESP_ERR_INVALID_ARG; } @@ -356,11 +353,11 @@ static esp_err_t actrls_process_action(const sys_btns_action* action, sys_btns_a } static esp_err_t actrls_process_press(const sys_btns_press* press, sys_btns_press* cur_config_press) { esp_err_t err = ESP_OK; - if (press->has_pressed) { + if(press->has_pressed) { cur_config_press->has_pressed = true; err = actrls_process_action(&press->pressed, &cur_config_press->pressed); } - if (err == ESP_OK && press->has_released) { + if(err == ESP_OK && press->has_released) { cur_config_press->has_released = true; err = actrls_process_action(&press->released, &cur_config_press->released); } @@ -371,7 +368,7 @@ static esp_err_t actrls_process_press(const sys_btns_press* press, sys_btns_pres */ static esp_err_t actrls_process_button(const sys_btns_btn* button, actrls_config_t* cur_config) { esp_err_t err = ESP_OK; - if (button->has_gpio && button->gpio.pin >= 0) { + if(button->has_gpio && button->gpio.pin >= 0) { cur_config->type = button->gpio.level == sys_gpio_lvl_LOW ? BUTTON_LOW : BUTTON_HIGH; cur_config->gpio = button->gpio.pin; } @@ -379,9 +376,9 @@ static esp_err_t actrls_process_button(const sys_btns_btn* button, actrls_config cur_config->debounce = button->debounce; cur_config->long_press = button->longduration; err = actrls_process_press(&button->normal, &cur_config->normal); - if (err == ESP_OK) err = actrls_process_press(&button->longpress, &cur_config->longpress); - if (err == ESP_OK) err = actrls_process_press(&button->shifted, &cur_config->shifted); - if (err == ESP_OK) err = actrls_process_press(&button->longshifted, &cur_config->longshifted); + if(err == ESP_OK) err = actrls_process_press(&button->longpress, &cur_config->longpress); + if(err == ESP_OK) err = actrls_process_press(&button->shifted, &cur_config->shifted); + if(err == ESP_OK) err = actrls_process_press(&button->longshifted, &cur_config->longshifted); cur_config->shifter_gpio = button->shifter; return err; } @@ -393,13 +390,11 @@ static actrls_config_t* actrls_init_alloc_structure(const sys_btns_profile* butt actrls_config_t* json_config = NULL; // Check if the main profiles array was created - if (!control_profiles) { - control_profiles = cJSON_CreateObject(); - } + if(!control_profiles) { control_profiles = cJSON_CreateObject(); } ESP_LOGD(TAG, "config contains %u button definitions", buttons->buttons_count); - if (buttons->buttons_count != 0) { + if(buttons->buttons_count != 0) { json_config = calloc(sizeof(actrls_config_t) * (buttons->buttons_count + 1), 1); - if (json_config) { + if(json_config) { json_config[buttons->buttons_count].gpio = -1; } else { ESP_LOGE(TAG, "Unable to allocate memory to hold configuration for %u buttons ", buttons->buttons_count); @@ -438,8 +433,8 @@ static void actrls_defaults(actrls_config_t* config) { */ static sys_btns_profile* get_profile(const char* profile_name) { ESP_LOGD(TAG, "Looking for profile name %s in %d profile(s)", profile_name, platform->dev.buttons_profiles_count); - for (int i = 0; i < platform->dev.buttons_profiles_count; i++) { - if (strcasecmp(platform->dev.buttons_profiles[i].profile_name, profile_name) == 0) { + for(int i = 0; i < platform->dev.buttons_profiles_count; i++) { + if(strcasecmp(platform->dev.buttons_profiles[i].profile_name, profile_name) == 0) { ESP_LOGD(TAG, "Found profile name %s", platform->dev.buttons_profiles[i].profile_name); return &platform->dev.buttons_profiles[i]; } else { @@ -459,36 +454,36 @@ static esp_err_t actrls_init_profile(const char* profile_name, bool create) { actrls_config_t* config_root = NULL; sys_btns_profile* config; - if (!profile_name || strlen(profile_name) == 0) { + if(!profile_name || strlen(profile_name) == 0) { ESP_LOGI(TAG, "No control button configured"); return ESP_OK; } ESP_LOGI(TAG, "Initializing button control profile %s", profile_name); config = get_profile(profile_name); - if (!config) { + if(!config) { ESP_LOGE(TAG, "Invalid button control profile %s", profile_name); goto exit; } - if (config->buttons_count == 0) { + if(config->buttons_count == 0) { ESP_LOGE(TAG, "No button found %s", profile_name); err = ESP_FAIL; } else { ESP_LOGD(TAG, "Number of buttons: %d", config->buttons_count); cur_config = config_root = actrls_init_alloc_structure(config, profile_name); - if (!cur_config) { + if(!cur_config) { ESP_LOGE(TAG, "Config buffer was empty. "); err = ESP_FAIL; goto exit; } ESP_LOGD(TAG, "Processing button definitions. "); - for (int i = 0; i < config->buttons_count; i++) { + for(int i = 0; i < config->buttons_count; i++) { ESP_LOGD(TAG, "Processing button %d of %d for profile %s. ", i + 1, config->buttons_count, profile_name); actrls_defaults(cur_config); esp_err_t loc_err = actrls_process_button(&config->buttons[i], cur_config); err = (err == ESP_OK) ? loc_err : err; - if (loc_err == ESP_OK) { - if (create) + if(loc_err == ESP_OK) { + if(create) button_create((void*)cur_config, cur_config->gpio, cur_config->type, cur_config->pull, cur_config->debounce, control_handler, cur_config->long_press, cur_config->shifter_gpio); } else { diff --git a/components/services/audio_controls.h b/components/services/audio_controls.h index b4b77f4e..d5c706a1 100644 --- a/components/services/audio_controls.h +++ b/components/services/audio_controls.h @@ -5,25 +5,25 @@ * https://opensource.org/licenses/MIT * */ - + #pragma once #include "buttons.h" #include "Buttons.pb.h" // BEWARE: this is the index of the array of action below (change actrls_action_s as well!) -// typedef enum { ACTRLS_NONE = -1, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY, -// ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT, -// BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT, +// typedef enum { ACTRLS_NONE = -1, ACTRLS_POWER, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY, +// ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT, +// BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT, // BCTRLS_PS0,BCTRLS_PS1,BCTRLS_PS2,BCTRLS_PS3,BCTRLS_PS4,BCTRLS_PS5,BCTRLS_PS6,BCTRLS_PS7,BCTRLS_PS8,BCTRLS_PS9, // KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH, // ACTRLS_SLEEP, -// ACTRLS_REMAP, ACTRLS_MAX +// ACTRLS_REMAP, ACTRLS_MAX // } actrls_action_e; typedef void (*actrls_handler)(bool pressed); -typedef actrls_handler actrls_t[sys_btns_actions_MAX- sys_btns_actions_A_NONE - 1]; -typedef bool actrls_hook_t(int gpio, sys_btns_action *action, button_event_e event, button_press_e press, bool long_press); +typedef actrls_handler actrls_t[sys_btns_actions_MAX - sys_btns_actions_A_NONE - 1]; +typedef bool actrls_hook_t(int gpio, sys_btns_action* action, button_event_e event, button_press_e press, bool long_press); typedef bool actrls_ir_handler_t(uint16_t addr, uint16_t cmd); // BEWARE any change to struct below must be mapped to actrls_config_map @@ -32,16 +32,16 @@ typedef bool actrls_ir_handler_t(uint16_t addr, uint16_t cmd); // const char * name; // } actrls_action_detail_t; typedef struct actrl_config_s { - int gpio; - int type; - bool pull; - int debounce; - int long_press; - int shifter_gpio; - sys_btns_press normal, longpress, shifted, longshifted; // [0] keypressed, [1] keyreleased + int gpio; + int type; + bool pull; + int debounce; + int long_press; + int shifter_gpio; + sys_btns_press normal, longpress, shifted, longshifted; // [0] keypressed, [1] keyreleased } actrls_config_t; -esp_err_t actrls_init(const char *profile_name); +esp_err_t actrls_init(const char* profile_name); /* Set hook function to non-null to be set your own direct managemet function, @@ -50,7 +50,7 @@ normal handling should be done The add_release boolean forces a release event to be sent if a press action has been set, whether a release action has been set or not */ -void actrls_set_default(const actrls_t controls, bool raw_controls, actrls_hook_t *hook, actrls_ir_handler_t *ir_handler); -void actrls_set(const actrls_t controls, bool raw_controls, actrls_hook_t *hook, actrls_ir_handler_t *ir_handler); +void actrls_set_default(const actrls_t controls, bool raw_controls, actrls_hook_t* hook, actrls_ir_handler_t* ir_handler); +void actrls_set(const actrls_t controls, bool raw_controls, actrls_hook_t* hook, actrls_ir_handler_t* ir_handler); void actrls_unset(void); bool actrls_ir_action(uint16_t addr, uint16_t code); diff --git a/components/services/battery.c b/components/services/battery.c index d4a1f050..4b6f4023 100644 --- a/components/services/battery.c +++ b/components/services/battery.c @@ -23,68 +23,67 @@ using ADC, AMP and HALL sensor. Rather than making battery aware, we just ignore if as the interrupt lasts 80ns and should be debounced (and the ADC read does not happen very often) -*/ +*/ -#define BATTERY_TIMER (10*1000) +#define BATTERY_TIMER (10 * 1000) -static const char *TAG = "battery"; +static const char* TAG = "battery"; static struct { - float sum, avg, scale; - int count; - sys_battery_config * battery_config; - TimerHandle_t timer; + float sum, avg, scale; + int count; + sys_battery_config* battery_config; + TimerHandle_t timer; } battery; -#define BATTERY_CHANNEL(b) (b.battery_config?b.battery_config->channel - sys_battery_channels_CH0:-1) -#define ATTENUATION(b) (b.battery_config?b.battery_config->atten - sys_battery_atten_ATT_0:-1) +#define BATTERY_CHANNEL(b) (b.battery_config ? b.battery_config->channel - sys_battery_channels_CH0 : -1) +#define ATTENUATION(b) (b.battery_config ? b.battery_config->atten - sys_battery_atten_ATT_0 : -1) void (*battery_handler_svc)(float value, int cells); /**************************************************************************************** * */ -float battery_value_svc(void) { - return battery.avg; - } - +float battery_value_svc(void) { return battery.avg; } + /**************************************************************************************** * */ uint8_t battery_level_svc(void) { - // TODO: this is vastly incorrect - if(!battery.battery_config){ return 0; } - int level = battery.avg ? (battery.avg - (3.0 * battery.battery_config->cells)) / ((4.2 - 3.0) * battery.battery_config->cells) * 100 : 0; - return level < 100 ? level : 100; + // TODO: this is vastly incorrect + if(!battery.battery_config) { return 0; } + int level = battery.avg ? (battery.avg - (3.0 * battery.battery_config->cells)) / ((4.2 - 3.0) * battery.battery_config->cells) * 100 : 0; + return level < 100 ? level : 100; } /**************************************************************************************** * */ static void battery_callback(TimerHandle_t xTimer) { - if(!battery.battery_config){ return; } - - battery.sum += adc1_get_raw(BATTERY_CHANNEL(battery)) * battery.battery_config->scale / 4095.0; - if (++battery.count == 30) { - battery.avg = battery.sum / battery.count; - battery.sum = battery.count = 0; - if (battery_handler_svc) (battery_handler_svc)(battery.avg, battery.battery_config->cells); - ESP_LOGI(TAG, "Voltage %.2fV", battery.avg); - } + if(!battery.battery_config) { return; } + + battery.sum += adc1_get_raw(BATTERY_CHANNEL(battery)) * battery.battery_config->scale / 4095.0; + if(++battery.count == 30) { + battery.avg = battery.sum / battery.count; + battery.sum = battery.count = 0; + if(battery_handler_svc) (battery_handler_svc)(battery.avg, battery.battery_config->cells); + ESP_LOGI(TAG, "Voltage %.2fV", battery.avg); + } } /**************************************************************************************** * */ void battery_svc_init(void) { - if (SYS_DEV_BATTERY(battery.battery_config) && BATTERY_CHANNEL(battery) != -1) { - adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten(BATTERY_CHANNEL(battery), ATTENUATION(battery)); + if(SYS_DEV_BATTERY(battery.battery_config) && BATTERY_CHANNEL(battery) != -1) { + adc1_config_width(ADC_WIDTH_BIT_12); + adc1_config_channel_atten(BATTERY_CHANNEL(battery), ATTENUATION(battery)); - battery.avg = adc1_get_raw(BATTERY_CHANNEL(battery)) * battery.scale / 4095.0; - battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_PERIOD_MS, pdTRUE, NULL, battery_callback); - xTimerStart(battery.timer, portMAX_DELAY); - - ESP_LOGI(TAG, "Battery measure channel: %u, scale %f, atten %d, cells %u, avg %.2fV", BATTERY_CHANNEL(battery), battery.scale, ATTENUATION(battery), battery.battery_config->cells, battery.avg); - } else { - ESP_LOGI(TAG, "No battery"); - } + battery.avg = adc1_get_raw(BATTERY_CHANNEL(battery)) * battery.scale / 4095.0; + battery.timer = xTimerCreate("battery", BATTERY_TIMER / portTICK_PERIOD_MS, pdTRUE, NULL, battery_callback); + xTimerStart(battery.timer, portMAX_DELAY); + + ESP_LOGI(TAG, "Battery measure channel: %u, scale %f, atten %d, cells %u, avg %.2fV", BATTERY_CHANNEL(battery), battery.scale, + ATTENUATION(battery), battery.battery_config->cells, battery.avg); + } else { + ESP_LOGI(TAG, "No battery"); + } } diff --git a/components/services/battery.h b/components/services/battery.h index c1b8dc5b..001d5b52 100644 --- a/components/services/battery.h +++ b/components/services/battery.h @@ -7,4 +7,3 @@ */ #pragma once - diff --git a/components/services/buttons.c b/components/services/buttons.c index 9e3c6ddf..19813216 100644 --- a/components/services/buttons.c +++ b/components/services/buttons.c @@ -84,8 +84,8 @@ static void common_task_init(void) { static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__((aligned(4))); static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__((aligned(4))); - if (!common_queue_set) { - ESP_LOGD(TAG,"Creating buttons task with a queue set length of %d",BUTTON_QUEUE_LEN+1); + if(!common_queue_set) { + ESP_LOGD(TAG, "Creating buttons task with a queue set length of %d", BUTTON_QUEUE_LEN + 1); common_queue_set = xQueueCreateSet(BUTTON_QUEUE_LEN + 1); xTaskCreateStatic((TaskFunction_t)buttons_task, "buttons", BUTTON_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 2, xStack, &xTaskBuffer); } @@ -98,19 +98,19 @@ static void IRAM_ATTR gpio_isr_handler(void* arg) { struct button_s* button = (struct button_s*)arg; BaseType_t woken = pdFALSE; - if (xTimerGetPeriod(button->timer) > pdMS_TO_TICKS(button->debounce)) { - if (button->gpio < GPIO_NUM_MAX) + if(xTimerGetPeriod(button->timer) > pdMS_TO_TICKS(button->debounce)) { + if(button->gpio < GPIO_NUM_MAX) xTimerChangePeriodFromISR(button->timer, pdMS_TO_TICKS(button->debounce), &woken); else xTimerChangePeriod(button->timer, pdMS_TO_TICKS(button->debounce), pdMS_TO_TICKS(10)); } else { - if (button->gpio < GPIO_NUM_MAX) + if(button->gpio < GPIO_NUM_MAX) xTimerResetFromISR(button->timer, &woken); else xTimerReset(button->timer, portMAX_DELAY); } - if (woken) portYIELD_FROM_ISR(); + if(woken) portYIELD_FROM_ISR(); ESP_EARLY_LOGD(TAG, "INT gpio %u level %u", button->gpio, button->level); } @@ -128,12 +128,12 @@ static void buttons_timer_handler(TimerHandle_t xTimer) { * Buttons polling timer */ static void buttons_polling(TimerHandle_t xTimer) { - for (int i = 0; polled_gpio[i].gpio != -1; i++) { - if (!polled_gpio[i].button) continue; + for(int i = 0; polled_gpio[i].gpio != -1; i++) { + if(!polled_gpio[i].button) continue; int level = gpio_get_level(polled_gpio[i].gpio); - if (level != polled_gpio[i].level) { + if(level != polled_gpio[i].level) { polled_gpio[i].level = level; buttons_handler(polled_gpio[i].button, level); } @@ -146,9 +146,9 @@ static void buttons_polling(TimerHandle_t xTimer) { static void buttons_handler(struct button_s* button, int level) { button->level = level; - if (button->shifter && button->shifter->type == button->shifter->level) button->shifter->shifting = true; + if(button->shifter && button->shifter->type == button->shifter->level) button->shifter->shifting = true; - if (button->long_press && !button->long_timer && button->level == button->type) { + if(button->long_press && !button->long_timer && button->level == button->type) { // detect a long press, so hold event generation ESP_LOGD(TAG, "setting long timer gpio:%u level:%u", button->gpio, button->level); xTimerChangePeriod(button->timer, button->long_press / portTICK_PERIOD_MS, 0); @@ -176,14 +176,14 @@ static void buttons_task(void* arg) { buttons_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); services_sleep_setsleeper(buttons_idle_callback); - while (1) { + while(1) { QueueSetMemberHandle_t xActivatedMember; bool active = true; // wait on button, rotary and infrared queues - if ((xActivatedMember = xQueueSelectFromSet(common_queue_set, portMAX_DELAY)) == NULL) continue; + if((xActivatedMember = xQueueSelectFromSet(common_queue_set, portMAX_DELAY)) == NULL) continue; - if (xActivatedMember == button_queue) { + if(xActivatedMember == button_queue) { struct button_s button; button_event_e event; button_press_e press; @@ -197,7 +197,7 @@ static void buttons_task(void* arg) { button.shifting); // find if shifting is activated - if (button.shifter && button.shifter->type == button.shifter->level) + if(button.shifter && button.shifter->type == button.shifter->level) press = BUTTON_SHIFTED; else press = BUTTON_NORMAL; @@ -207,26 +207,26 @@ static void buttons_task(void* arg) { or we have a release before the long press timer elapsed, so two events shall be sent */ - if (button.long_timer) { - if (event == BUTTON_RELEASED) { + if(button.long_timer) { + if(event == BUTTON_RELEASED) { // early release of a long-press button, send press/release - if (!button.shifting) { + if(!button.shifting) { button.handler(button.client, BUTTON_PRESSED, press, false); button.handler(button.client, BUTTON_RELEASED, press, false); } // button is a copy, so need to go to real context button.self->shifting = false; - } else if (!button.shifting) { + } else if(!button.shifting) { // normal long press and not shifting so don't discard button.handler(button.client, BUTTON_PRESSED, press, true); } } else { // normal press/release of a button or release of a long-press button - if (!button.shifting) button.handler(button.client, event, press, button.long_press); + if(!button.shifting) button.handler(button.client, event, press, button.long_press); // button is a copy, so need to go to real context button.self->shifting = false; } - } else if (xActivatedMember == rotary.queue) { + } else if(xActivatedMember == rotary.queue) { rotary_encoder_event_t event = {0}; // received a rotary event @@ -242,7 +242,7 @@ static void buttons_task(void* arg) { } // mark the last activity - if (active) buttons_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); + if(active) buttons_idle_since = pdTICKS_TO_MS(xTaskGetTickCount()); } } @@ -255,13 +255,13 @@ void dummy_handler(void* id, button_event_e event, button_press_e press) { ESP_L * Create buttons */ void button_create(void* client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio) { - if (n_buttons >= MAX_BUTTONS) return; + if(n_buttons >= MAX_BUTTONS) return; ESP_LOGI(TAG, "Creating button using GPIO %u, type %s, %s pull-up/down, long press %u shifter %d", gpio, - sys_gpio_lvl_name(type == 0 ? sys_gpio_lvl_LOW : sys_gpio_lvl_HIGH), pull?"with":"without", long_press, shifter_gpio); + sys_gpio_lvl_name(type == 0 ? sys_gpio_lvl_LOW : sys_gpio_lvl_HIGH), pull ? "with" : "without", long_press, shifter_gpio); - if (!n_buttons) { - ESP_LOGD(TAG,"Creating new buttton message queue with a length of %d entries",BUTTON_QUEUE_LEN); + if(!n_buttons) { + ESP_LOGD(TAG, "Creating new buttton message queue with a length of %d entries", BUTTON_QUEUE_LEN); button_queue = xQueueCreate(BUTTON_QUEUE_LEN, sizeof(struct button_s)); common_task_init(); xQueueAddToSet(button_queue, common_queue_set); @@ -282,15 +282,15 @@ void button_create(void* client, int gpio, int type, bool pull, int debounce, bu xTimerCreate("buttonTimer", buttons[n_buttons].debounce / portTICK_PERIOD_MS, pdFALSE, (void*)&buttons[n_buttons], buttons_timer_handler); buttons[n_buttons].self = buttons + n_buttons; - for (int i = 0; i < n_buttons; i++) { + for(int i = 0; i < n_buttons; i++) { // first try to find our shifter - if (buttons[i].gpio == shifter_gpio) { + if(buttons[i].gpio == shifter_gpio) { buttons[n_buttons].shifter = buttons + i; // a shifter must have a long-press handler - if (!buttons[i].long_press) buttons[i].long_press = -1; + if(!buttons[i].long_press) buttons[i].long_press = -1; } // then try to see if we are a non-assigned shifter - if (buttons[i].shifter_gpio == gpio) { + if(buttons[i].shifter_gpio == gpio) { buttons[i].shifter = buttons + n_buttons; ESP_LOGI(TAG, "post-assigned shifter gpio %u", buttons[i].gpio); } @@ -300,9 +300,9 @@ void button_create(void* client, int gpio, int type, bool pull, int debounce, bu gpio_set_direction_x(gpio, GPIO_MODE_INPUT); // do we need pullup or pulldown - if (pull) { - if (GPIO_IS_VALID_OUTPUT_GPIO(gpio) || gpio >= GPIO_NUM_MAX) { - if (type == BUTTON_LOW) + if(pull) { + if(GPIO_IS_VALID_OUTPUT_GPIO(gpio) || gpio >= GPIO_NUM_MAX) { + if(type == BUTTON_LOW) gpio_set_pull_mode_x(gpio, GPIO_PULLUP_ONLY); else gpio_set_pull_mode_x(gpio, GPIO_PULLDOWN_ONLY); @@ -315,9 +315,9 @@ void button_create(void* client, int gpio, int type, bool pull, int debounce, bu buttons[n_buttons].level = gpio_get_level_x(gpio); // nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated - for (int i = 0; polled_gpio[i].gpio != -1; i++) - if (polled_gpio[i].gpio == gpio) { - if (!polled_timer) { + for(int i = 0; polled_gpio[i].gpio != -1; i++) + if(polled_gpio[i].gpio == gpio) { + if(!polled_timer) { polled_timer = xTimerCreate("buttonsPolling", 100 / portTICK_PERIOD_MS, pdTRUE, polled_gpio, buttons_polling); xTimerStart(polled_timer, portMAX_DELAY); } @@ -331,7 +331,7 @@ void button_create(void* client, int gpio, int type, bool pull, int debounce, bu } // only create ISR if this is not a polled gpio - if (gpio != -1) { + if(gpio != -1) { // we need any edge detection gpio_set_intr_type_x(gpio, GPIO_INTR_ANYEDGE); gpio_isr_handler_add_x(gpio, gpio_isr_handler, buttons + n_buttons); @@ -345,8 +345,8 @@ void button_create(void* client, int gpio, int type, bool pull, int debounce, bu * Get stored id */ void* button_get_client(int gpio) { - for (int i = 0; i < n_buttons; i++) { - if (buttons[i].gpio == gpio) return buttons[i].client; + for(int i = 0; i < n_buttons; i++) { + if(buttons[i].gpio == gpio) return buttons[i].client; } return NULL; } @@ -355,10 +355,10 @@ void* button_get_client(int gpio) { * Get stored id */ bool button_is_pressed(int gpio, void* client) { - for (int i = 0; i < n_buttons; i++) { - if (gpio != -1 && buttons[i].gpio == gpio) + for(int i = 0; i < n_buttons; i++) { + if(gpio != -1 && buttons[i].gpio == gpio) return buttons[i].level == buttons[i].type; - else if (client && buttons[i].client == client) + else if(client && buttons[i].client == client) return buttons[i].level == buttons[i].type; } return false; @@ -375,15 +375,15 @@ void* button_remap(void* client, int gpio, button_handler handler, int long_pres ESP_LOGI(TAG, "remapping GPIO %u, long press %u shifter %u", gpio, long_press, shifter_gpio); // find button - for (i = 0; i < n_buttons; i++) { - if (buttons[i].gpio == gpio) { + for(i = 0; i < n_buttons; i++) { + if(buttons[i].gpio == gpio) { button = buttons + i; break; } } // don't know what we are doing here - if (!button) return NULL; + if(!button) return NULL; prev_client = button->client; button->client = client; @@ -392,11 +392,11 @@ void* button_remap(void* client, int gpio, button_handler handler, int long_pres button->shifter_gpio = shifter_gpio; // find our shifter (if any) - for (i = 0; shifter_gpio != -1 && i < n_buttons; i++) { - if (buttons[i].gpio == shifter_gpio) { + for(i = 0; shifter_gpio != -1 && i < n_buttons; i++) { + if(buttons[i].gpio == shifter_gpio) { button->shifter = buttons + i; // a shifter must have a long-press handler - if (!buttons[i].long_press) buttons[i].long_press = -1; + if(!buttons[i].long_press) buttons[i].long_press = -1; break; } } @@ -417,7 +417,7 @@ static void rotary_button_handler(void* id, button_event_e event, button_press_e */ bool create_rotary(void* id, int A, int B, int SW, int long_press, rotary_handler handler) { // nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated - if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) { + if(A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) { ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B); return false; } @@ -439,7 +439,7 @@ bool create_rotary(void* id, int A, int B, int SW, int long_press, rotary_handle xQueueAddToSet(rotary.queue, common_queue_set); // create companion button if rotary has a switch - if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1); + if(SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1); ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW); diff --git a/components/services/buttons.h b/components/services/buttons.h index 042991d6..76ed2ce8 100644 --- a/components/services/buttons.h +++ b/components/services/buttons.h @@ -9,14 +9,14 @@ #pragma once #include "infrared.h" - -// button type (pressed = LOW or HIGH, matches GPIO level) -#define BUTTON_LOW 0 -#define BUTTON_HIGH 1 -typedef enum { BUTTON_PRESSED, BUTTON_RELEASED } button_event_e; -typedef enum { BUTTON_NORMAL, BUTTON_SHIFTED } button_press_e; -typedef void (*button_handler)(void *id, button_event_e event, button_press_e mode, bool long_press); +// button type (pressed = LOW or HIGH, matches GPIO level) +#define BUTTON_LOW 0 +#define BUTTON_HIGH 1 + +typedef enum { BUTTON_PRESSED, BUTTON_RELEASED } button_event_e; +typedef enum { BUTTON_NORMAL, BUTTON_SHIFTED } button_press_e; +typedef void (*button_handler)(void* id, button_event_e event, button_press_e mode, bool long_press); /* set debounce to 0 for default (50ms) @@ -25,14 +25,14 @@ set shifter_gpio to -1 for no shift NOTE: shifter buttons *must* be created before shiftee */ -void button_create(void *client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio); -void *button_remap(void *client, int gpio, button_handler handler, int long_press, int shifter_gpio); -void *button_get_client(int gpio); -bool button_is_pressed(int gpio, void *client); +void button_create(void* client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio); +void* button_remap(void* client, int gpio, button_handler handler, int long_press, int shifter_gpio); +void* button_get_client(int gpio); +bool button_is_pressed(int gpio, void* client); -typedef enum { ROTARY_LEFT, ROTARY_RIGHT, ROTARY_PRESSED, ROTARY_RELEASED } rotary_event_e; -typedef void (*rotary_handler)(void *id, rotary_event_e event, bool long_press); +typedef enum { ROTARY_LEFT, ROTARY_RIGHT, ROTARY_PRESSED, ROTARY_RELEASED } rotary_event_e; +typedef void (*rotary_handler)(void* id, rotary_event_e event, bool long_press); -bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler); +bool create_rotary(void* id, int A, int B, int SW, int long_press, rotary_handler handler); bool create_infrared(int gpio, infrared_handler handler, infrared_mode_t mode); diff --git a/components/services/globdefs.h b/components/services/globdefs.h index a5ae7039..de5f1778 100644 --- a/components/services/globdefs.h +++ b/components/services/globdefs.h @@ -7,10 +7,10 @@ * https://opensource.org/licenses/MIT * */ - + #pragma once -#define SPI_SYSTEM_HOST SPI2_HOST +#define SPI_SYSTEM_HOST SPI2_HOST #define RMT_NEXT_TX_CHANNEL() rmt_system_base_tx_channel++; #define RMT_NEXT_RX_CHANNEL() rmt_system_base_rx_channel--; @@ -20,6 +20,6 @@ extern int spi_system_dc_gpio; extern int rmt_system_base_tx_channel; extern int rmt_system_base_rx_channel; typedef struct { - int timer, base_channel, max; + int timer, base_channel, max; } pwm_system_t; extern pwm_system_t pwm_system; diff --git a/components/services/gpio_exp.c b/components/services/gpio_exp.c index c83877b8..62d4d0e1 100644 --- a/components/services/gpio_exp.c +++ b/components/services/gpio_exp.c @@ -19,117 +19,127 @@ #include "driver/spi_master.h" #include "gpio_exp.h" #include "GPIO.pb.h" -#define GPIO_EXP_INTR 0x100 -#define GPIO_EXP_WRITE 0x200 +#define GPIO_EXP_INTR 0x100 +#define GPIO_EXP_WRITE 0x200 /* shadow register is both output and input, so we assume that reading to the ports also reads the value set on output */ - + typedef struct gpio_exp_s { - uint32_t first, last; - int intr; - bool intr_pending; - struct { - struct gpio_exp_phy_s phy; - spi_device_handle_t spi_handle; - }; - uint32_t shadow, pending; - TickType_t age; - SemaphoreHandle_t mutex; - uint32_t r_mask, w_mask; - uint32_t pullup, pulldown; - struct gpio_exp_isr_s { - gpio_isr_t handler; - void *arg; - TimerHandle_t timer; - } isr[32]; - struct gpio_exp_model_s const *model; + uint32_t first, last; + int intr; + bool intr_pending; + struct { + struct gpio_exp_phy_s phy; + spi_device_handle_t spi_handle; + }; + uint32_t shadow, pending; + TickType_t age; + SemaphoreHandle_t mutex; + uint32_t r_mask, w_mask; + uint32_t pullup, pulldown; + struct gpio_exp_isr_s { + gpio_isr_t handler; + void* arg; + TimerHandle_t timer; + } isr[32]; + struct gpio_exp_model_s const* model; } gpio_exp_t; typedef struct { - enum { ASYNC_WRITE } type; - int gpio; - int level; - gpio_exp_t *expander; + enum { ASYNC_WRITE } type; + int gpio; + int level; + gpio_exp_t* expander; } queue_request_t; static const char TAG[] = "gpio expander"; -static void IRAM_ATTR intr_isr_handler(void* arg); -static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio); +static void IRAM_ATTR intr_isr_handler(void* arg); +static gpio_exp_t* find_expander(gpio_exp_t* expander, int* gpio); static esp_err_t mpr121_init(gpio_exp_t* self); -static uint32_t mpr121_read(gpio_exp_t* self); -static void mpr121_write(gpio_exp_t* self); +static uint32_t mpr121_read(gpio_exp_t* self); +static void mpr121_write(gpio_exp_t* self); -static void pca9535_set_direction(gpio_exp_t* self); +static void pca9535_set_direction(gpio_exp_t* self); static uint32_t pca9535_read(gpio_exp_t* self); -static void pca9535_write(gpio_exp_t* self); +static void pca9535_write(gpio_exp_t* self); -static uint32_t pca85xx_read(gpio_exp_t* self); -static void pca85xx_write(gpio_exp_t* self); +static uint32_t pca85xx_read(gpio_exp_t* self); +static void pca85xx_write(gpio_exp_t* self); static esp_err_t mcp23017_init(gpio_exp_t* self); -static void mcp23017_set_pull_mode(gpio_exp_t* self); -static void mcp23017_set_direction(gpio_exp_t* self); -static uint32_t mcp23017_read(gpio_exp_t* self); -static void mcp23017_write(gpio_exp_t* self); +static void mcp23017_set_pull_mode(gpio_exp_t* self); +static void mcp23017_set_direction(gpio_exp_t* self); +static uint32_t mcp23017_read(gpio_exp_t* self); +static void mcp23017_write(gpio_exp_t* self); static esp_err_t mcp23s17_init(gpio_exp_t* self); -static void mcp23s17_set_pull_mode(gpio_exp_t* self); -static void mcp23s17_set_direction(gpio_exp_t* self); -static uint32_t mcp23s17_read(gpio_exp_t* self); -static void mcp23s17_write(gpio_exp_t* self); +static void mcp23s17_set_pull_mode(gpio_exp_t* self); +static void mcp23s17_set_direction(gpio_exp_t* self); +static uint32_t mcp23s17_read(gpio_exp_t* self); +static void mcp23s17_write(gpio_exp_t* self); -static void service_handler(void *arg); -static void debounce_handler( TimerHandle_t xTimer ); +static void service_handler(void* arg); +static void debounce_handler(TimerHandle_t xTimer); static esp_err_t i2c_write(uint8_t port, uint8_t addr, uint8_t reg, uint32_t data, int len); -static uint32_t i2c_read(uint8_t port, uint8_t addr, uint8_t reg, int len); +static uint32_t i2c_read(uint8_t port, uint8_t addr, uint8_t reg, int len); -static spi_device_handle_t spi_config(struct gpio_exp_phy_s *phy); -static esp_err_t spi_write(spi_device_handle_t handle, uint8_t addr, uint8_t reg, uint32_t data, int len); -static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg, int len); +static spi_device_handle_t spi_config(struct gpio_exp_phy_s* phy); +static esp_err_t spi_write(spi_device_handle_t handle, uint8_t addr, uint8_t reg, uint32_t data, int len); +static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg, int len); static const struct gpio_exp_model_s { - char *model; - gpio_int_type_t trigger; - esp_err_t (*init)(gpio_exp_t* self); - uint32_t (*read)(gpio_exp_t* self); - void (*write)(gpio_exp_t* self); - void (*set_direction)(gpio_exp_t* self); - void (*set_pull_mode)(gpio_exp_t* self); + char* model; + gpio_int_type_t trigger; + esp_err_t (*init)(gpio_exp_t* self); + uint32_t (*read)(gpio_exp_t* self); + void (*write)(gpio_exp_t* self); + void (*set_direction)(gpio_exp_t* self); + void (*set_pull_mode)(gpio_exp_t* self); } registered[] = { - { .model = "mpr121", - .trigger = GPIO_INTR_LOW_LEVEL, - .init = mpr121_init, - .read = mpr121_read, - .write = mpr121_write, }, - { .model = "pca9535", - .trigger = GPIO_INTR_LOW_LEVEL, - .set_direction = pca9535_set_direction, - .read = pca9535_read, - .write = pca9535_write, }, - { .model = "pca85xx", - .trigger = GPIO_INTR_LOW_LEVEL, - .read = pca85xx_read, - .write = pca85xx_write, }, - { .model = "mcp23017", - .trigger = GPIO_INTR_LOW_LEVEL, - .init = mcp23017_init, - .set_direction = mcp23017_set_direction, - .set_pull_mode = mcp23017_set_pull_mode, - .read = mcp23017_read, - .write = mcp23017_write, }, - { .model = "mcp23s17", - .trigger = GPIO_INTR_LOW_LEVEL, - .init = mcp23s17_init, - .set_direction = mcp23s17_set_direction, - .set_pull_mode = mcp23s17_set_pull_mode, - .read = mcp23s17_read, - .write = mcp23s17_write, }, + { + .model = "mpr121", + .trigger = GPIO_INTR_LOW_LEVEL, + .init = mpr121_init, + .read = mpr121_read, + .write = mpr121_write, + }, + { + .model = "pca9535", + .trigger = GPIO_INTR_LOW_LEVEL, + .set_direction = pca9535_set_direction, + .read = pca9535_read, + .write = pca9535_write, + }, + { + .model = "pca85xx", + .trigger = GPIO_INTR_LOW_LEVEL, + .read = pca85xx_read, + .write = pca85xx_write, + }, + { + .model = "mcp23017", + .trigger = GPIO_INTR_LOW_LEVEL, + .init = mcp23017_init, + .set_direction = mcp23017_set_direction, + .set_pull_mode = mcp23017_set_pull_mode, + .read = mcp23017_read, + .write = mcp23017_write, + }, + { + .model = "mcp23s17", + .trigger = GPIO_INTR_LOW_LEVEL, + .init = mcp23s17_init, + .set_direction = mcp23s17_set_direction, + .set_pull_mode = mcp23s17_set_pull_mode, + .read = mcp23s17_read, + .write = mcp23s17_write, + }, }; static EXT_RAM_ATTR uint8_t n_expanders; @@ -140,379 +150,378 @@ static EXT_RAM_ATTR TaskHandle_t service_task; /****************************************************************************** * Retrieve base from an expander reference */ -uint32_t gpio_exp_get_base(gpio_exp_t *expander) { - return expander->first; -} +uint32_t gpio_exp_get_base(gpio_exp_t* expander) { return expander->first; } /****************************************************************************** * Retrieve reference from a GPIO */ -gpio_exp_t *gpio_exp_get_expander(int gpio) { - int _gpio = gpio; - return find_expander(NULL, &_gpio); +gpio_exp_t* gpio_exp_get_expander(int gpio) { + int _gpio = gpio; + return find_expander(NULL, &_gpio); } /****************************************************************************** * Create an I2C expander */ -gpio_exp_t* gpio_exp_create(const gpio_exp_config_t *config) { - gpio_exp_t *expander = expanders + n_expanders; - - if (config->base < GPIO_NUM_MAX || n_expanders == sizeof(expanders)/sizeof(gpio_exp_t)) { - ESP_LOGE(TAG, "Base %d GPIO must be at least %d for %s or too many expanders %d", config->base, GPIO_NUM_MAX, config->model, n_expanders); - return NULL; - } +gpio_exp_t* gpio_exp_create(const gpio_exp_config_t* config) { + gpio_exp_t* expander = expanders + n_expanders; - // See if we know that model (expanders is zero-initialized) - for (int i = 0; !expander->model && i < sizeof(registered)/sizeof(struct gpio_exp_model_s); i++) { - if (strcasestr(config->model, registered[i].model)) expander->model = registered + i; + if(config->base < GPIO_NUM_MAX || n_expanders == sizeof(expanders) / sizeof(gpio_exp_t)) { + ESP_LOGE(TAG, "Base %d GPIO must be at least %d for %s or too many expanders %d", config->base, GPIO_NUM_MAX, config->model, n_expanders); + return NULL; } - // well... try again - if (!expander->model) { - ESP_LOGE(TAG, "Unknown GPIO expansion chip %s", config->model); - return NULL; - } - - memcpy(&expander->phy, &config->phy, sizeof(struct gpio_exp_phy_s)); + // See if we know that model (expanders is zero-initialized) + for(int i = 0; !expander->model && i < sizeof(registered) / sizeof(struct gpio_exp_model_s); i++) { + if(strcasestr(config->model, registered[i].model)) expander->model = registered + i; + } - // try to initialize the expander if required - if (expander->model->init && expander->model->init(expander) != ESP_OK) { - ESP_LOGE(TAG, "Cannot create GPIO expander %s, check i2c/spi configuration", config->model); - return NULL; - } - n_expanders++; - expander->first = config->base; - expander->last = config->base + config->count - 1; - expander->intr = config->intr; - expander->mutex = xSemaphoreCreateMutex(); + // well... try again + if(!expander->model) { + ESP_LOGE(TAG, "Unknown GPIO expansion chip %s", config->model); + return NULL; + } - // create a task to handle asynchronous requests (only write at this time) - if (!message_queue) { - // we allocate TCB but stack is static to avoid SPIRAM fragmentation - StaticTask_t* xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - static EXT_RAM_ATTR StackType_t xStack[4*1024] __attribute__ ((aligned (4))); + memcpy(&expander->phy, &config->phy, sizeof(struct gpio_exp_phy_s)); - message_queue = xQueueCreate(4, sizeof(queue_request_t)); - service_task = xTaskCreateStatic(service_handler, "gpio_expander", sizeof(xStack), NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer); - } - if(config->phy.ena_pin>=0){ - ESP_LOGD(TAG,"Enabling expander with pin %d level %d",config->phy.ena_pin,config->phy.ena_lvl); - esp_rom_gpio_pad_select_gpio(config->phy.ena_pin); - gpio_set_direction(config->phy.ena_pin, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(config->phy.ena_pin, config->phy.ena_lvl); - } + // try to initialize the expander if required + if(expander->model->init && expander->model->init(expander) != ESP_OK) { + ESP_LOGE(TAG, "Cannot create GPIO expander %s, check i2c/spi configuration", config->model); + return NULL; + } + n_expanders++; + expander->first = config->base; + expander->last = config->base + config->count - 1; + expander->intr = config->intr; + expander->mutex = xSemaphoreCreateMutex(); - // set interrupt if possible - if (config->intr >= 0) { - esp_rom_gpio_pad_select_gpio(config->intr); - gpio_set_direction(config->intr, GPIO_MODE_INPUT); + // create a task to handle asynchronous requests (only write at this time) + if(!message_queue) { + // we allocate TCB but stack is static to avoid SPIRAM fragmentation + StaticTask_t* xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + static EXT_RAM_ATTR StackType_t xStack[4 * 1024] __attribute__((aligned(4))); - switch (expander->model->trigger) { - case GPIO_INTR_NEGEDGE: - case GPIO_INTR_LOW_LEVEL: - gpio_set_pull_mode(config->intr, GPIO_PULLUP_ONLY); - break; - case GPIO_INTR_POSEDGE: - case GPIO_INTR_HIGH_LEVEL: - gpio_set_pull_mode(config->intr, GPIO_PULLDOWN_ONLY); - break; - default: - gpio_set_pull_mode(config->intr, GPIO_PULLUP_PULLDOWN); - break; - } - - gpio_set_intr_type(config->intr, expander->model->trigger); - gpio_isr_handler_add(config->intr, intr_isr_handler, expander); - gpio_intr_enable(config->intr); - } - - ESP_LOGI(TAG, "Create GPIO expander %s at base %u with intr %d at @%x on port/host %d/%d, enable pin: %d:%d", config->model, config->base, config->intr, config->phy.addr, config->phy.port, config->phy.host,config->phy.ena_pin,config->phy.ena_lvl); - return expander; + message_queue = xQueueCreate(4, sizeof(queue_request_t)); + service_task = xTaskCreateStatic(service_handler, "gpio_expander", sizeof(xStack), NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer); + } + if(config->phy.ena_pin >= 0) { + ESP_LOGD(TAG, "Enabling expander with pin %d level %d", config->phy.ena_pin, config->phy.ena_lvl); + esp_rom_gpio_pad_select_gpio(config->phy.ena_pin); + gpio_set_direction(config->phy.ena_pin, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(config->phy.ena_pin, config->phy.ena_lvl); + } + + // set interrupt if possible + if(config->intr >= 0) { + esp_rom_gpio_pad_select_gpio(config->intr); + gpio_set_direction(config->intr, GPIO_MODE_INPUT); + + switch(expander->model->trigger) { + case GPIO_INTR_NEGEDGE: + case GPIO_INTR_LOW_LEVEL: + gpio_set_pull_mode(config->intr, GPIO_PULLUP_ONLY); + break; + case GPIO_INTR_POSEDGE: + case GPIO_INTR_HIGH_LEVEL: + gpio_set_pull_mode(config->intr, GPIO_PULLDOWN_ONLY); + break; + default: + gpio_set_pull_mode(config->intr, GPIO_PULLUP_PULLDOWN); + break; + } + + gpio_set_intr_type(config->intr, expander->model->trigger); + gpio_isr_handler_add(config->intr, intr_isr_handler, expander); + gpio_intr_enable(config->intr); + } + + ESP_LOGI(TAG, "Create GPIO expander %s at base %u with intr %d at @%x on port/host %d/%d, enable pin: %d:%d", config->model, config->base, + config->intr, config->phy.addr, config->phy.port, config->phy.host, config->phy.ena_pin, config->phy.ena_lvl); + return expander; } /****************************************************************************** * Add ISR handler for a GPIO */ -esp_err_t gpio_exp_isr_handler_add(int gpio, gpio_isr_t isr_handler, uint32_t debounce, void *arg, struct gpio_exp_s *expander) { - if (gpio < GPIO_NUM_MAX && !expander) return gpio_isr_handler_add(gpio, isr_handler, arg); - if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; +esp_err_t gpio_exp_isr_handler_add(int gpio, gpio_isr_t isr_handler, uint32_t debounce, void* arg, struct gpio_exp_s* expander) { + if(gpio < GPIO_NUM_MAX && !expander) return gpio_isr_handler_add(gpio, isr_handler, arg); + if((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; - expander->isr[gpio].handler = isr_handler; - expander->isr[gpio].arg = arg; - if (debounce) expander->isr[gpio].timer = xTimerCreate("gpioExpDebounce", pdMS_TO_TICKS(debounce), - pdFALSE, expander->isr + gpio, debounce_handler ); + expander->isr[gpio].handler = isr_handler; + expander->isr[gpio].arg = arg; + if(debounce) + expander->isr[gpio].timer = xTimerCreate("gpioExpDebounce", pdMS_TO_TICKS(debounce), pdFALSE, expander->isr + gpio, debounce_handler); - return ESP_OK; + return ESP_OK; } /****************************************************************************** * Remove ISR handler for a GPIO */ -esp_err_t gpio_exp_isr_handler_remove(int gpio, struct gpio_exp_s *expander) { - if (gpio < GPIO_NUM_MAX && !expander) return gpio_isr_handler_remove(gpio); - if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; +esp_err_t gpio_exp_isr_handler_remove(int gpio, struct gpio_exp_s* expander) { + if(gpio < GPIO_NUM_MAX && !expander) return gpio_isr_handler_remove(gpio); + if((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; - if (expander->isr[gpio].timer) xTimerDelete(expander->isr[gpio].timer, portMAX_DELAY); - memset(expander->isr + gpio, 0, sizeof(struct gpio_exp_isr_s)); + if(expander->isr[gpio].timer) xTimerDelete(expander->isr[gpio].timer, portMAX_DELAY); + memset(expander->isr + gpio, 0, sizeof(struct gpio_exp_isr_s)); - return ESP_OK; + return ESP_OK; } /****************************************************************************** * Set GPIO direction */ -esp_err_t gpio_exp_set_direction(int gpio, gpio_mode_t mode, gpio_exp_t *expander) { - if (gpio < GPIO_NUM_MAX && !expander) return gpio_set_direction(gpio, mode); - if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; +esp_err_t gpio_exp_set_direction(int gpio, gpio_mode_t mode, gpio_exp_t* expander) { + if(gpio < GPIO_NUM_MAX && !expander) return gpio_set_direction(gpio, mode); + if((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; - xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(portMAX_DELAY)); + xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(portMAX_DELAY)); - if (mode == GPIO_MODE_INPUT) { - expander->r_mask |= 1 << gpio; - expander->shadow = expander->model->read(expander); - expander->age = ~xTaskGetTickCount(); - } else { - expander->w_mask |= 1 << gpio; - } - - if (expander->r_mask & expander->w_mask) { - xSemaphoreGive(expander->mutex); - ESP_LOGE(TAG, "GPIO %d on expander base %u can't be r/w", gpio, expander->first); - return ESP_ERR_INVALID_ARG; - } + if(mode == GPIO_MODE_INPUT) { + expander->r_mask |= 1 << gpio; + expander->shadow = expander->model->read(expander); + expander->age = ~xTaskGetTickCount(); + } else { + expander->w_mask |= 1 << gpio; + } - // most expanders want unconfigured GPIO to be set to output - if (expander->model->set_direction) expander->model->set_direction(expander); + if(expander->r_mask & expander->w_mask) { + xSemaphoreGive(expander->mutex); + ESP_LOGE(TAG, "GPIO %d on expander base %u can't be r/w", gpio, expander->first); + return ESP_ERR_INVALID_ARG; + } - xSemaphoreGive(expander->mutex); + // most expanders want unconfigured GPIO to be set to output + if(expander->model->set_direction) expander->model->set_direction(expander); - return ESP_OK; -} + xSemaphoreGive(expander->mutex); + + return ESP_OK; +} /****************************************************************************** * Get GPIO level with cache */ -int gpio_exp_get_level(int gpio, int age, gpio_exp_t *expander) { - if (gpio < GPIO_NUM_MAX && !expander) return gpio_get_level(gpio); - if ((expander = find_expander(expander, &gpio)) == NULL) return -1; - uint32_t now = xTaskGetTickCount(); +int gpio_exp_get_level(int gpio, int age, gpio_exp_t* expander) { + if(gpio < GPIO_NUM_MAX && !expander) return gpio_get_level(gpio); + if((expander = find_expander(expander, &gpio)) == NULL) return -1; + uint32_t now = xTaskGetTickCount(); - // return last thing we had if we can't get the mutex - if (xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50)) == pdFALSE) { - ESP_LOGW(TAG, "Can't get mutex for GPIO %d", expander->first + gpio); - return (expander->shadow >> gpio) & 0x01; - } + // return last thing we had if we can't get the mutex + if(xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50)) == pdFALSE) { + ESP_LOGW(TAG, "Can't get mutex for GPIO %d", expander->first + gpio); + return (expander->shadow >> gpio) & 0x01; + } - // re-read the expander if data is too old - if (age >= 0 && now - expander->age >= pdMS_TO_TICKS(age)) { - uint32_t value = expander->model->read(expander); - expander->pending |= (expander->shadow ^ value) & expander->r_mask; - expander->shadow = value; - expander->age = now; - } + // re-read the expander if data is too old + if(age >= 0 && now - expander->age >= pdMS_TO_TICKS(age)) { + uint32_t value = expander->model->read(expander); + expander->pending |= (expander->shadow ^ value) & expander->r_mask; + expander->shadow = value; + expander->age = now; + } - // clear pending bit - expander->pending &= ~(1 << gpio); + // clear pending bit + expander->pending &= ~(1 << gpio); - xSemaphoreGive(expander->mutex); - - ESP_LOGD(TAG, "Get level for GPIO %u => read %x", expander->first + gpio, expander->shadow); - return (expander->shadow >> gpio) & 0x01; + xSemaphoreGive(expander->mutex); + + ESP_LOGD(TAG, "Get level for GPIO %u => read %x", expander->first + gpio, expander->shadow); + return (expander->shadow >> gpio) & 0x01; } /****************************************************************************** * Set GPIO level with cache */ -esp_err_t gpio_exp_set_level(int gpio, int level, bool direct, gpio_exp_t *expander) { - if (gpio < GPIO_NUM_MAX && !expander) return gpio_set_level(gpio, level); - if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; - uint32_t mask = 1 << gpio; +esp_err_t gpio_exp_set_level(int gpio, int level, bool direct, gpio_exp_t* expander) { + if(gpio < GPIO_NUM_MAX && !expander) return gpio_set_level(gpio, level); + if((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG; + uint32_t mask = 1 << gpio; - // very limited risk with lack of semaphore here - if ((expander->w_mask & mask) == 0) { - ESP_LOGW(TAG, "GPIO %d is not set for output", expander->first + gpio); - return ESP_ERR_INVALID_ARG; - } + // very limited risk with lack of semaphore here + if((expander->w_mask & mask) == 0) { + ESP_LOGW(TAG, "GPIO %d is not set for output", expander->first + gpio); + return ESP_ERR_INVALID_ARG; + } - if (direct) { - xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(portMAX_DELAY)); + if(direct) { + xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(portMAX_DELAY)); - level = level ? mask : 0; - mask &= expander->shadow; + level = level ? mask : 0; + mask &= expander->shadow; - // only write if shadow not up to date - if ((mask ^ level) && expander->model->write) { - expander->shadow = (expander->shadow & ~(mask | level)) | level; - expander->model->write(expander); - } + // only write if shadow not up to date + if((mask ^ level) && expander->model->write) { + expander->shadow = (expander->shadow & ~(mask | level)) | level; + expander->model->write(expander); + } - xSemaphoreGive(expander->mutex); - ESP_LOGD(TAG, "Set level %x for GPIO %u => wrote %x", level, expander->first + gpio, expander->shadow); - } else { - queue_request_t request = { .gpio = gpio, .level = level, .type = ASYNC_WRITE, .expander = expander }; - if (xQueueSend(message_queue, &request, 0) == pdFALSE) return ESP_ERR_INVALID_RESPONSE; + xSemaphoreGive(expander->mutex); + ESP_LOGD(TAG, "Set level %x for GPIO %u => wrote %x", level, expander->first + gpio, expander->shadow); + } else { + queue_request_t request = {.gpio = gpio, .level = level, .type = ASYNC_WRITE, .expander = expander}; + if(xQueueSend(message_queue, &request, 0) == pdFALSE) return ESP_ERR_INVALID_RESPONSE; - // notify service task that will write it when it can - xTaskNotify(service_task, GPIO_EXP_WRITE, eSetValueWithoutOverwrite); - } + // notify service task that will write it when it can + xTaskNotify(service_task, GPIO_EXP_WRITE, eSetValueWithoutOverwrite); + } - return ESP_OK; + return ESP_OK; } /****************************************************************************** * Set GPIO pullmode */ -esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, gpio_exp_t *expander) { - if (gpio < GPIO_NUM_MAX && !expander) return gpio_set_pull_mode(gpio, mode); - if ((expander = find_expander(expander, &gpio)) != NULL && expander->model->set_pull_mode) { +esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, gpio_exp_t* expander) { + if(gpio < GPIO_NUM_MAX && !expander) return gpio_set_pull_mode(gpio, mode); + if((expander = find_expander(expander, &gpio)) != NULL && expander->model->set_pull_mode) { - expander->pullup &= ~(1 << gpio); - expander->pulldown &= ~(1 << gpio); + expander->pullup &= ~(1 << gpio); + expander->pulldown &= ~(1 << gpio); - if (mode == GPIO_PULLUP_ONLY || mode == GPIO_PULLUP_PULLDOWN) expander->pullup |= 1 << gpio; - if (mode == GPIO_PULLDOWN_ONLY || mode == GPIO_PULLUP_PULLDOWN) expander->pulldown |= 1 << gpio; + if(mode == GPIO_PULLUP_ONLY || mode == GPIO_PULLUP_PULLDOWN) expander->pullup |= 1 << gpio; + if(mode == GPIO_PULLDOWN_ONLY || mode == GPIO_PULLUP_PULLDOWN) expander->pulldown |= 1 << gpio; - expander->model->set_pull_mode(expander); - return ESP_OK; - } - return ESP_ERR_INVALID_ARG; + expander->model->set_pull_mode(expander); + return ESP_OK; + } + return ESP_ERR_INVALID_ARG; } /****************************************************************************** * Wrapper function */ -void esp_rom_gpio_pad_select_gpio_x(uint32_t gpio){ - if (gpio < GPIO_NUM_MAX) { - esp_rom_gpio_pad_select_gpio(gpio); - } +void esp_rom_gpio_pad_select_gpio_x(uint32_t gpio) { + if(gpio < GPIO_NUM_MAX) { esp_rom_gpio_pad_select_gpio(gpio); } } esp_err_t gpio_set_pull_mode_x(int gpio, gpio_pull_mode_t mode) { - if (gpio < GPIO_NUM_MAX) return gpio_set_pull_mode(gpio, mode); - return gpio_exp_set_pull_mode(gpio, mode, NULL); + if(gpio < GPIO_NUM_MAX) return gpio_set_pull_mode(gpio, mode); + return gpio_exp_set_pull_mode(gpio, mode, NULL); } esp_err_t gpio_set_direction_x(int gpio, gpio_mode_t mode) { - if (gpio < GPIO_NUM_MAX) return gpio_set_direction(gpio, mode); - return gpio_exp_set_direction(gpio, mode, NULL); + if(gpio < GPIO_NUM_MAX) return gpio_set_direction(gpio, mode); + return gpio_exp_set_direction(gpio, mode, NULL); } int gpio_get_level_x(int gpio) { - if (gpio < GPIO_NUM_MAX) return gpio_get_level(gpio); - return gpio_exp_get_level(gpio, 10, NULL); + if(gpio < GPIO_NUM_MAX) return gpio_get_level(gpio); + return gpio_exp_get_level(gpio, 10, NULL); } esp_err_t gpio_set_level_x(int gpio, int level) { - if (gpio < GPIO_NUM_MAX) return gpio_set_level(gpio, level); - return gpio_exp_set_level(gpio, level, false, NULL); + if(gpio < GPIO_NUM_MAX) return gpio_set_level(gpio, level); + return gpio_exp_set_level(gpio, level, false, NULL); } esp_err_t gpio_isr_handler_add_x(int gpio, gpio_isr_t isr_handler, void* args) { - if (gpio < GPIO_NUM_MAX) return gpio_isr_handler_add(gpio, isr_handler, args); - return gpio_exp_isr_handler_add(gpio, isr_handler, 0, args, NULL); + if(gpio < GPIO_NUM_MAX) return gpio_isr_handler_add(gpio, isr_handler, args); + return gpio_exp_isr_handler_add(gpio, isr_handler, 0, args, NULL); } esp_err_t gpio_isr_handler_remove_x(int gpio) { - if (gpio < GPIO_NUM_MAX) return gpio_isr_handler_remove(gpio); - return gpio_exp_isr_handler_remove(gpio, NULL); + if(gpio < GPIO_NUM_MAX) return gpio_isr_handler_remove(gpio); + return gpio_exp_isr_handler_remove(gpio, NULL); } - /**************************************************************************************** * INTR low-level handler */ static void IRAM_ATTR intr_isr_handler(void* arg) { - gpio_exp_t *self = (gpio_exp_t*) arg; - BaseType_t woken = pdFALSE; - - // edge interrupts do not work because of read/clear = potential short pulse - gpio_intr_disable(self->intr); - - // activate all, including ourselves - for (int i = 0; i < n_expanders; i++) if (expanders[i].intr == self->intr) expanders[i].intr_pending = true; - - xTaskNotifyFromISR(service_task, GPIO_EXP_INTR, eSetValueWithOverwrite, &woken); - if (woken) portYIELD_FROM_ISR(); + gpio_exp_t* self = (gpio_exp_t*)arg; + BaseType_t woken = pdFALSE; - ESP_EARLY_LOGD(TAG, "INTR for expander base %d", gpio_exp_get_base(self)); + // edge interrupts do not work because of read/clear = potential short pulse + gpio_intr_disable(self->intr); + + // activate all, including ourselves + for(int i = 0; i < n_expanders; i++) + if(expanders[i].intr == self->intr) expanders[i].intr_pending = true; + + xTaskNotifyFromISR(service_task, GPIO_EXP_INTR, eSetValueWithOverwrite, &woken); + if(woken) portYIELD_FROM_ISR(); + + ESP_EARLY_LOGD(TAG, "INTR for expander base %d", gpio_exp_get_base(self)); } /**************************************************************************************** * INTR debounce handler */ -static void debounce_handler( TimerHandle_t xTimer ) { - struct gpio_exp_isr_s *isr = (struct gpio_exp_isr_s*) pvTimerGetTimerID (xTimer); - isr->handler(isr->arg); +static void debounce_handler(TimerHandle_t xTimer) { + struct gpio_exp_isr_s* isr = (struct gpio_exp_isr_s*)pvTimerGetTimerID(xTimer); + isr->handler(isr->arg); } /**************************************************************************************** * Service task */ -void service_handler(void *arg) { - while (1) { - queue_request_t request; - uint32_t notif = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); +void service_handler(void* arg) { + while(1) { + queue_request_t request; + uint32_t notif = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - // we have been notified of an interrupt - if (notif == GPIO_EXP_INTR) { - /* If we want a smarter bitmap of expanders with a pending interrupt + // we have been notified of an interrupt + if(notif == GPIO_EXP_INTR) { + /* If we want a smarter bitmap of expanders with a pending interrupt we'll have to disable interrupts while clearing that bitmap. For now, a loop will do */ - for (int i = 0; i < n_expanders; i++) { - gpio_exp_t *expander = expanders + i; + for(int i = 0; i < n_expanders; i++) { + gpio_exp_t* expander = expanders + i; - // no interrupt for that gpio or not pending (safe as interrupt is disabled) - if (expander->intr < 0 || !expander->intr_pending) continue; + // no interrupt for that gpio or not pending (safe as interrupt is disabled) + if(expander->intr < 0 || !expander->intr_pending) continue; - xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50)); + xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50)); - // read GPIOs and clear all pending status - uint32_t value = expander->model->read(expander); - expander->age = xTaskGetTickCount(); - - // re-enable interrupt now that it has been cleared - expander->intr_pending = false; - gpio_intr_enable(expander->intr); - - uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask); - expander->shadow = value; - expander->pending = 0; + // read GPIOs and clear all pending status + uint32_t value = expander->model->read(expander); + expander->age = xTaskGetTickCount(); - xSemaphoreGive(expander->mutex); - ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending); - - for (int gpio = 31, clz = 0; pending && clz < 31; pending <<= (clz + 1)) { - clz = __builtin_clz(pending); - gpio -= clz; - if (expander->isr[gpio].timer) xTimerReset(expander->isr[gpio].timer, 1); // todo 0 - else if (expander->isr[gpio].handler) expander->isr[gpio].handler(expander->isr[gpio].arg); - } - } - } + // re-enable interrupt now that it has been cleared + expander->intr_pending = false; + gpio_intr_enable(expander->intr); - // check if we have some other pending requests - while (xQueueReceive(message_queue, &request, 0) == pdTRUE) { - esp_err_t err = gpio_exp_set_level(request.gpio, request.level, true, request.expander); - if (err != ESP_OK) ESP_LOGW(TAG, "Can't execute async GPIO %d write request (%d)", request.gpio, err); - } - } + uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask); + expander->shadow = value; + expander->pending = 0; + + xSemaphoreGive(expander->mutex); + ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending); + + for(int gpio = 31, clz = 0; pending && clz < 31; pending <<= (clz + 1)) { + clz = __builtin_clz(pending); + gpio -= clz; + if(expander->isr[gpio].timer) + xTimerReset(expander->isr[gpio].timer, 1); // todo 0 + else if(expander->isr[gpio].handler) + expander->isr[gpio].handler(expander->isr[gpio].arg); + } + } + } + + // check if we have some other pending requests + while(xQueueReceive(message_queue, &request, 0) == pdTRUE) { + esp_err_t err = gpio_exp_set_level(request.gpio, request.level, true, request.expander); + if(err != ESP_OK) ESP_LOGW(TAG, "Can't execute async GPIO %d write request (%d)", request.gpio, err); + } + } } /**************************************************************************************** * Find the expander related to base */ -static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio) { - // a mutex would be better, but risk is so small... - for (int i = 0; !expander && i < n_expanders; i++) { - if (*gpio >= expanders[i].first && *gpio <= expanders[i].last) expander = expanders + i; - } - - // normalize GPIO number - if (expander && *gpio >= expander->first) *gpio -= expander->first; - - return expander; +static gpio_exp_t* find_expander(gpio_exp_t* expander, int* gpio) { + // a mutex would be better, but risk is so small... + for(int i = 0; !expander && i < n_expanders; i++) { + if(*gpio >= expanders[i].first && *gpio <= expanders[i].last) expander = expanders + i; + } + + // normalize GPIO number + if(expander && *gpio >= expander->first) *gpio -= expander->first; + + return expander; } /**************************************************************************************** @@ -523,165 +532,147 @@ static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio) { * MPR121 family : init, direction, read and write */ static esp_err_t mpr121_init(gpio_exp_t* self) { - static const struct { - uint8_t addr; - uint8_t data; - } mpr121_init_table[] = { - { 0x80, 0x63 }, /* Soft reset */ + static const struct { + uint8_t addr; + uint8_t data; + } mpr121_init_table[] = {{0x80, 0x63}, /* Soft reset */ - { 0x2b, 0x01 }, { 0x2c, 0x01 }, { 0x2d, 0x10 }, { 0x2e, 0x20 }, /* MHDR, NHDR, NCLR, FDLR */ - { 0x2f, 0x01 }, { 0x30, 0x01 }, { 0x31, 0x10 }, { 0x32, 0x20 }, /* MHDF, NHDF, NCLF, FDLF */ - { 0x33, 0x01 }, { 0x34, 0x10 }, { 0x35, 0xff }, /* NHDT, NCLT, FDLT */ - { 0x5b, 0x11 }, { 0x5c, 0xff }, { 0x5d, 0x30 }, /* DTR, AFE1, AFE2 */ - { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x00 }, { 0x7e, 0x00 }, { 0x7f, 0x00 },/* ACCR0, ACCR1, USL, LSL, TL */ + {0x2b, 0x01}, {0x2c, 0x01}, {0x2d, 0x10}, {0x2e, 0x20}, /* MHDR, NHDR, NCLR, FDLR */ + {0x2f, 0x01}, {0x30, 0x01}, {0x31, 0x10}, {0x32, 0x20}, /* MHDF, NHDF, NCLF, FDLF */ + {0x33, 0x01}, {0x34, 0x10}, {0x35, 0xff}, /* NHDT, NCLT, FDLT */ + {0x5b, 0x11}, {0x5c, 0xff}, {0x5d, 0x30}, /* DTR, AFE1, AFE2 */ + {0x7b, 0x00}, {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00}, /* ACCR0, ACCR1, USL, LSL, TL */ - { 0x41, 0x28 }, { 0x42, 0x14 }, /* ELE0: Touch Threshold, Release Threshold */ - { 0x43, 0x28 }, { 0x44, 0x14 }, /* ELE1: Touch Threshold, Release Threshold */ - { 0x45, 0x28 }, { 0x46, 0x14 }, /* ELE2: Touch Threshold, Release Threshold */ - { 0x47, 0x28 }, { 0x48, 0x14 }, /* ELE3: Touch Threshold, Release Threshold */ - { 0x49, 0x28 }, { 0x4a, 0x14 }, /* ELE4: Touch Threshold, Release Threshold */ - { 0x4b, 0x28 }, { 0x4c, 0x14 }, /* ELE5: Touch Threshold, Release Threshold */ - { 0x4d, 0x28 }, { 0x4e, 0x14 }, /* ELE6: Touch Threshold, Release Threshold */ - { 0x4f, 0x28 }, { 0x50, 0x14 }, /* ELE7: Touch Threshold, Release Threshold */ - { 0x51, 0x28 }, { 0x52, 0x14 }, /* ELE8: Touch Threshold, Release Threshold */ - { 0x53, 0x28 }, { 0x54, 0x14 }, /* ELE9: Touch Threshold, Release Threshold */ - { 0x55, 0x28 }, { 0x56, 0x14 }, /* ELE10: Touch Threshold, Release Threshold */ - { 0x57, 0x28 }, { 0x58, 0x14 }, /* ELE11: Touch Threshold, Release Threshold */ + {0x41, 0x28}, {0x42, 0x14}, /* ELE0: Touch Threshold, Release Threshold */ + {0x43, 0x28}, {0x44, 0x14}, /* ELE1: Touch Threshold, Release Threshold */ + {0x45, 0x28}, {0x46, 0x14}, /* ELE2: Touch Threshold, Release Threshold */ + {0x47, 0x28}, {0x48, 0x14}, /* ELE3: Touch Threshold, Release Threshold */ + {0x49, 0x28}, {0x4a, 0x14}, /* ELE4: Touch Threshold, Release Threshold */ + {0x4b, 0x28}, {0x4c, 0x14}, /* ELE5: Touch Threshold, Release Threshold */ + {0x4d, 0x28}, {0x4e, 0x14}, /* ELE6: Touch Threshold, Release Threshold */ + {0x4f, 0x28}, {0x50, 0x14}, /* ELE7: Touch Threshold, Release Threshold */ + {0x51, 0x28}, {0x52, 0x14}, /* ELE8: Touch Threshold, Release Threshold */ + {0x53, 0x28}, {0x54, 0x14}, /* ELE9: Touch Threshold, Release Threshold */ + {0x55, 0x28}, {0x56, 0x14}, /* ELE10: Touch Threshold, Release Threshold */ + {0x57, 0x28}, {0x58, 0x14}, /* ELE11: Touch Threshold, Release Threshold */ - { 0x5e, 0xcc }, /* ECR - must be set last */ - { 0, 0 } - }; + {0x5e, 0xcc}, /* ECR - must be set last */ + {0, 0}}; - esp_err_t err = 0; - for (int i = 0; mpr121_init_table[i].addr; i++) { - err |= i2c_write(self->phy.port, self->phy.addr, mpr121_init_table[i].addr, mpr121_init_table[i].data, 1); - } + esp_err_t err = 0; + for(int i = 0; mpr121_init_table[i].addr; i++) { + err |= i2c_write(self->phy.port, self->phy.addr, mpr121_init_table[i].addr, mpr121_init_table[i].data, 1); + } - return err; + return err; } static uint32_t mpr121_read(gpio_exp_t* self) { - // only return the lower 12 bits of the pin status registers - return i2c_read(self->phy.port, self->phy.addr, 0x00, 2) & 0x0fff; + // only return the lower 12 bits of the pin status registers + return i2c_read(self->phy.port, self->phy.addr, 0x00, 2) & 0x0fff; } -static void mpr121_write(gpio_exp_t* self) { - ESP_LOGE(TAG, "MPR121 GPIO write not implemented"); -} +static void mpr121_write(gpio_exp_t* self) { ESP_LOGE(TAG, "MPR121 GPIO write not implemented"); } /**************************************************************************************** * PCA9535 family : direction, read and write */ -static void pca9535_set_direction(gpio_exp_t* self) { - i2c_write(self->phy.port, self->phy.addr, 0x06, self->r_mask, 2); -} +static void pca9535_set_direction(gpio_exp_t* self) { i2c_write(self->phy.port, self->phy.addr, 0x06, self->r_mask, 2); } -static uint32_t pca9535_read(gpio_exp_t* self) { - return i2c_read(self->phy.port, self->phy.addr, 0x00, 2); -} +static uint32_t pca9535_read(gpio_exp_t* self) { return i2c_read(self->phy.port, self->phy.addr, 0x00, 2); } -static void pca9535_write(gpio_exp_t* self) { - i2c_write(self->phy.port, self->phy.addr, 0x02, self->shadow, 2); -} +static void pca9535_write(gpio_exp_t* self) { i2c_write(self->phy.port, self->phy.addr, 0x02, self->shadow, 2); } /**************************************************************************************** * PCA85xx family : read and write */ static uint32_t pca85xx_read(gpio_exp_t* self) { - // must return the full set of pins, not just inputs - uint32_t data = i2c_read(self->phy.port, self->phy.addr, 0xff, 2); - return (data & self->r_mask) | (self->shadow & ~self->r_mask); + // must return the full set of pins, not just inputs + uint32_t data = i2c_read(self->phy.port, self->phy.addr, 0xff, 2); + return (data & self->r_mask) | (self->shadow & ~self->r_mask); } static void pca85xx_write(gpio_exp_t* self) { - /* + /* There is no good option with this chip: normally, unused pin should be set to input to avoid any conflict but then they float and create tons of suprious. So option 1 is to le tthem float and option 2 is to set them as output to 0. In addition, setting an output pin to 1 equals is making it an input and if this is use to short a led (e.g.) instead of being the sink, the it generates a spurious */ - // option 1 - // i2c_write(self->phy.port, self->phy.addr, 0xff, (self->shadow & self->w_mask) | ~self->w_mask, 2); - // option 2 - i2c_write(self->phy.port, self->phy.addr, 0xff, (self->shadow & self->w_mask) | self->r_mask, 2); + // option 1 + // i2c_write(self->phy.port, self->phy.addr, 0xff, (self->shadow & self->w_mask) | ~self->w_mask, 2); + // option 2 + i2c_write(self->phy.port, self->phy.addr, 0xff, (self->shadow & self->w_mask) | self->r_mask, 2); } /**************************************************************************************** * MCP23017 family : init, direction, read and write */ static esp_err_t mcp23017_init(gpio_exp_t* self) { - /* + /* 0111 x10x = same bank, mirrot single int, no sequentµial, open drain, active low not sure about this funny change of mapping of the control register itself, really? */ - esp_err_t err = i2c_write(self->phy.port, self->phy.addr, 0x05, 0x74, 1); - err |= i2c_write(self->phy.port, self->phy.addr, 0x0a, 0x74, 1); + esp_err_t err = i2c_write(self->phy.port, self->phy.addr, 0x05, 0x74, 1); + err |= i2c_write(self->phy.port, self->phy.addr, 0x0a, 0x74, 1); - // no interrupt on comparison or on change - err |= i2c_write(self->phy.port, self->phy.addr, 0x04, 0x00, 2); - err |= i2c_write(self->phy.port, self->phy.addr, 0x08, 0x00, 2); + // no interrupt on comparison or on change + err |= i2c_write(self->phy.port, self->phy.addr, 0x04, 0x00, 2); + err |= i2c_write(self->phy.port, self->phy.addr, 0x08, 0x00, 2); - return err; + return err; } static void mcp23017_set_direction(gpio_exp_t* self) { - // default to input and set real input to generate interrupt - i2c_write(self->phy.port, self->phy.addr, 0x00, ~self->w_mask, 2); - i2c_write(self->phy.port, self->phy.addr, 0x04, self->r_mask, 2); + // default to input and set real input to generate interrupt + i2c_write(self->phy.port, self->phy.addr, 0x00, ~self->w_mask, 2); + i2c_write(self->phy.port, self->phy.addr, 0x04, self->r_mask, 2); } -static void mcp23017_set_pull_mode(gpio_exp_t* self) { - i2c_write(self->phy.port, self->phy.addr, 0x0c, self->pullup, 2); -} +static void mcp23017_set_pull_mode(gpio_exp_t* self) { i2c_write(self->phy.port, self->phy.addr, 0x0c, self->pullup, 2); } static uint32_t mcp23017_read(gpio_exp_t* self) { - // read the pins value, not the stored one @interrupt - return i2c_read(self->phy.port, self->phy.addr, 0x12, 2); + // read the pins value, not the stored one @interrupt + return i2c_read(self->phy.port, self->phy.addr, 0x12, 2); } -static void mcp23017_write(gpio_exp_t* self) { - i2c_write(self->phy.port, self->phy.addr, 0x12, self->shadow, 2); -} +static void mcp23017_write(gpio_exp_t* self) { i2c_write(self->phy.port, self->phy.addr, 0x12, self->shadow, 2); } /**************************************************************************************** * MCP23s17 family : init, direction, read and write */ static esp_err_t mcp23s17_init(gpio_exp_t* self) { - if ((self->spi_handle = spi_config(&self->phy)) == NULL) return ESP_ERR_INVALID_ARG; - - /* + if((self->spi_handle = spi_config(&self->phy)) == NULL) return ESP_ERR_INVALID_ARG; + + /* 0111 x10x = same bank, mirrot single int, no sequentµial, open drain, active low not sure about this funny change of mapping of the control register itself, really? */ - esp_err_t err = spi_write(self->spi_handle, self->phy.addr, 0x05, 0x74, 1); - err |= spi_write(self->spi_handle, self->phy.addr, 0x0a, 0x74, 1); + esp_err_t err = spi_write(self->spi_handle, self->phy.addr, 0x05, 0x74, 1); + err |= spi_write(self->spi_handle, self->phy.addr, 0x0a, 0x74, 1); - // no interrupt on comparison or on change - err |= spi_write(self->spi_handle, self->phy.addr, 0x04, 0x00, 2); - err |= spi_write(self->spi_handle, self->phy.addr, 0x08, 0x00, 2); + // no interrupt on comparison or on change + err |= spi_write(self->spi_handle, self->phy.addr, 0x04, 0x00, 2); + err |= spi_write(self->spi_handle, self->phy.addr, 0x08, 0x00, 2); - return err; + return err; } static void mcp23s17_set_direction(gpio_exp_t* self) { - // default to input and set real input to generate interrupt - spi_write(self->spi_handle, self->phy.addr, 0x00, ~self->w_mask, 2); - spi_write(self->spi_handle, self->phy.addr, 0x04, self->r_mask, 2); + // default to input and set real input to generate interrupt + spi_write(self->spi_handle, self->phy.addr, 0x00, ~self->w_mask, 2); + spi_write(self->spi_handle, self->phy.addr, 0x04, self->r_mask, 2); } -static void mcp23s17_set_pull_mode(gpio_exp_t* self) { - spi_write(self->spi_handle, self->phy.addr, 0x0c, self->pullup, 2); -} +static void mcp23s17_set_pull_mode(gpio_exp_t* self) { spi_write(self->spi_handle, self->phy.addr, 0x0c, self->pullup, 2); } static uint32_t mcp23s17_read(gpio_exp_t* self) { - // read the pins value, not the stored one @interrupt - return spi_read(self->spi_handle, self->phy.addr, 0x12, 2); + // read the pins value, not the stored one @interrupt + return spi_read(self->spi_handle, self->phy.addr, 0x12, 2); } -static void mcp23s17_write(gpio_exp_t* self) { - spi_write(self->spi_handle, self->phy.addr, 0x12, self->shadow, 2); -} +static void mcp23s17_write(gpio_exp_t* self) { spi_write(self->spi_handle, self->phy.addr, 0x12, self->shadow, 2); } /*************************************************************************************** I2C low level @@ -691,24 +682,24 @@ static void mcp23s17_write(gpio_exp_t* self) { * I2C write up to 32 bits */ static esp_err_t i2c_write(uint8_t port, uint8_t addr, uint8_t reg, uint32_t data, int len) { - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); - - i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); - if (reg != 0xff) i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); - // works with our endianness - if (len > 1) i2c_master_write(cmd, (uint8_t*) &data, len, I2C_MASTER_NACK); - else i2c_master_write_byte(cmd, data, I2C_MASTER_NACK); - - i2c_master_stop(cmd); - esp_err_t ret = i2c_master_cmd_begin(port, cmd, 100 / portTICK_PERIOD_MS); + i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); + if(reg != 0xff) i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); + + // works with our endianness + if(len > 1) + i2c_master_write(cmd, (uint8_t*)&data, len, I2C_MASTER_NACK); + else + i2c_master_write_byte(cmd, data, I2C_MASTER_NACK); + + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(port, cmd, 100 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - - if (ret != ESP_OK) { - ESP_LOGW(TAG, "I2C write failed"); - } - + + if(ret != ESP_OK) { ESP_LOGW(TAG, "I2C write failed"); } + return ret; } @@ -716,35 +707,35 @@ static esp_err_t i2c_write(uint8_t port, uint8_t addr, uint8_t reg, uint32_t dat * I2C read up to 32 bits */ static uint32_t i2c_read(uint8_t port, uint8_t addr, uint8_t reg, int len) { - uint32_t data = 0; - - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + uint32_t data = 0; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); - // when using a register, write it's value then the device address again - if (reg != 0xff) { - i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); - i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); - } else { - i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); - } - - // works with our endianness - if (len > 1) i2c_master_read(cmd, (uint8_t*) &data, len, I2C_MASTER_LAST_NACK); - else i2c_master_read_byte(cmd, (uint8_t*) &data, I2C_MASTER_NACK); - + // when using a register, write it's value then the device address again + if(reg != 0xff) { + i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK); + i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); + } else { + i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK); + } + + // works with our endianness + if(len > 1) + i2c_master_read(cmd, (uint8_t*)&data, len, I2C_MASTER_LAST_NACK); + else + i2c_master_read_byte(cmd, (uint8_t*)&data, I2C_MASTER_NACK); + i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(port, cmd, 100 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); - - if (ret != ESP_OK) { - ESP_LOGW(TAG, "I2C read failed"); - } - return data; + if(ret != ESP_OK) { ESP_LOGW(TAG, "I2C read failed"); } + + return data; } /*************************************************************************************** @@ -754,55 +745,56 @@ static uint32_t i2c_read(uint8_t port, uint8_t addr, uint8_t reg, int len) { /**************************************************************************************** * SPI device addition */ -static spi_device_handle_t spi_config(struct gpio_exp_phy_s *phy) { - spi_device_interface_config_t config = { }; +static spi_device_handle_t spi_config(struct gpio_exp_phy_s* phy) { + spi_device_interface_config_t config = {}; spi_device_handle_t handle = NULL; - config.command_bits = config.address_bits = 8; + config.command_bits = config.address_bits = 8; config.clock_speed_hz = phy->speed ? phy->speed : SPI_MASTER_FREQ_8M; config.spics_io_num = phy->cs_pin; config.queue_size = 1; - config.flags = SPI_DEVICE_NO_DUMMY; + config.flags = SPI_DEVICE_NO_DUMMY; - spi_bus_add_device( phy->host, &config, &handle ); - ESP_LOGI(TAG, "SPI expander initialized on host:%d with cs:%d and speed:%dHz", phy->host, phy->cs_pin, config.clock_speed_hz); + spi_bus_add_device(phy->host, &config, &handle); + ESP_LOGI(TAG, "SPI expander initialized on host:%d with cs:%d and speed:%dHz", phy->host, phy->cs_pin, config.clock_speed_hz); - return handle; + return handle; } /**************************************************************************************** * SPI write up to 32 bits */ static esp_err_t spi_write(spi_device_handle_t handle, uint8_t addr, uint8_t reg, uint32_t data, int len) { - spi_transaction_t transaction = { }; + spi_transaction_t transaction = {}; - // rx_buffer is NULL, nothing to receive - transaction.flags = SPI_TRANS_USE_TXDATA; - transaction.cmd = addr << 1; - transaction.addr = reg; - transaction.tx_data[0] = data; transaction.tx_data[1] = data >> 8; - transaction.length = len * 8; + // rx_buffer is NULL, nothing to receive + transaction.flags = SPI_TRANS_USE_TXDATA; + transaction.cmd = addr << 1; + transaction.addr = reg; + transaction.tx_data[0] = data; + transaction.tx_data[1] = data >> 8; + transaction.length = len * 8; - // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) - return spi_device_polling_transmit(handle, &transaction); + // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) + return spi_device_polling_transmit(handle, &transaction); } /**************************************************************************************** * SPI read up to 32 bits */ static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg, int len) { - spi_transaction_t *transaction = heap_caps_calloc(1, sizeof(spi_transaction_t), MALLOC_CAP_DMA); + spi_transaction_t* transaction = heap_caps_calloc(1, sizeof(spi_transaction_t), MALLOC_CAP_DMA); - // tx_buffer is NULL, nothing to transmit except cmd/addr - transaction->flags = SPI_TRANS_USE_RXDATA; - transaction->cmd = (addr << 1) | 0x01; - transaction->addr = reg; - transaction->length = len * 8; + // tx_buffer is NULL, nothing to transmit except cmd/addr + transaction->flags = SPI_TRANS_USE_RXDATA; + transaction->cmd = (addr << 1) | 0x01; + transaction->addr = reg; + transaction->length = len * 8; - // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) - spi_device_polling_transmit(handle, transaction); - uint32_t data = *(uint32_t*) transaction->rx_data; - free(transaction); + // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) + spi_device_polling_transmit(handle, transaction); + uint32_t data = *(uint32_t*)transaction->rx_data; + free(transaction); - return data; + return data; } \ No newline at end of file diff --git a/components/services/gpio_exp.h b/components/services/gpio_exp.h index 6db0e1cb..743fe5d5 100644 --- a/components/services/gpio_exp.h +++ b/components/services/gpio_exp.h @@ -16,50 +16,59 @@ struct gpio_exp_s; typedef struct { - char model[32]; - int intr; - uint8_t count; - uint32_t base; - struct gpio_exp_phy_s { - uint8_t addr; - struct { // for I2C - uint8_t port; - }; - struct { // for SPI - uint32_t speed; - uint8_t host; - uint8_t cs_pin; - }; - int8_t ena_pin; // enable pin - int8_t ena_lvl; // enable level - } phy; + char model[32]; + int intr; + uint8_t count; + uint32_t base; + struct gpio_exp_phy_s { + uint8_t addr; + struct { // for I2C + uint8_t port; + }; + struct { // for SPI + uint32_t speed; + uint8_t host; + uint8_t cs_pin; + }; + int8_t ena_pin; // enable pin + int8_t ena_lvl; // enable level + } phy; } gpio_exp_config_t; // set to -1 and to NULL if there is no interrupt -struct gpio_exp_s* gpio_exp_create(const gpio_exp_config_t *config); -uint32_t gpio_exp_get_base(struct gpio_exp_s *expander); -struct gpio_exp_s* gpio_exp_get_expander(int gpio); -#define gpio_is_expanded(gpio) (gpio < GPIO_NUM_MAX) +struct gpio_exp_s* gpio_exp_create(const gpio_exp_config_t* config); +uint32_t gpio_exp_get_base(struct gpio_exp_s* expander); +struct gpio_exp_s* gpio_exp_get_expander(int gpio); +#define gpio_is_expanded(gpio) (gpio < GPIO_NUM_MAX) /* For all functions below when is provided, GPIO's can be numbered from 0. If is NULL, then GPIO must start from base OR be on-chip */ void esp_rom_gpio_pad_select_gpio_x(uint32_t iopad_num); -esp_err_t gpio_exp_set_direction(int gpio, gpio_mode_t mode, struct gpio_exp_s *expander); -esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, struct gpio_exp_s *expander); -int gpio_exp_get_level(int gpio, int age, struct gpio_exp_s *expander); -esp_err_t gpio_exp_set_level(int gpio, int level, bool direct, struct gpio_exp_s *expander); -esp_err_t gpio_exp_isr_handler_add(int gpio, gpio_isr_t isr, uint32_t debounce, void *arg, struct gpio_exp_s *expander); -esp_err_t gpio_exp_isr_handler_remove(int gpio, struct gpio_exp_s *expander); +esp_err_t gpio_exp_set_direction(int gpio, gpio_mode_t mode, struct gpio_exp_s* expander); +esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, struct gpio_exp_s* expander); +int gpio_exp_get_level(int gpio, int age, struct gpio_exp_s* expander); +esp_err_t gpio_exp_set_level(int gpio, int level, bool direct, struct gpio_exp_s* expander); +esp_err_t gpio_exp_isr_handler_add(int gpio, gpio_isr_t isr, uint32_t debounce, void* arg, struct gpio_exp_s* expander); +esp_err_t gpio_exp_isr_handler_remove(int gpio, struct gpio_exp_s* expander); // unified function to use either built-in or expanded GPIO -esp_err_t gpio_set_direction_x(int gpio, gpio_mode_t mode); -esp_err_t gpio_set_pull_mode_x(int gpio, gpio_pull_mode_t mode); -int gpio_get_level_x(int gpio); -esp_err_t gpio_set_level_x(int gpio, int level); -esp_err_t gpio_isr_handler_add_x(int gpio, gpio_isr_t isr_handler, void* args); -esp_err_t gpio_isr_handler_remove_x(int gpio); -#define gpio_set_intr_type_x(gpio, type) do { if (gpio < GPIO_NUM_MAX) gpio_set_intr_type(gpio, type); } while (0) -#define gpio_intr_enable_x(gpio) do { if (gpio < GPIO_NUM_MAX) gpio_intr_enable(gpio); } while (0) -#define gpio_pad_select_gpio_x(gpio) do { if (gpio < GPIO_NUM_MAX) esp_rom_gpio_pad_select_gpio(gpio); } while (0) +esp_err_t gpio_set_direction_x(int gpio, gpio_mode_t mode); +esp_err_t gpio_set_pull_mode_x(int gpio, gpio_pull_mode_t mode); +int gpio_get_level_x(int gpio); +esp_err_t gpio_set_level_x(int gpio, int level); +esp_err_t gpio_isr_handler_add_x(int gpio, gpio_isr_t isr_handler, void* args); +esp_err_t gpio_isr_handler_remove_x(int gpio); +#define gpio_set_intr_type_x(gpio, type) \ + do { \ + if(gpio < GPIO_NUM_MAX) gpio_set_intr_type(gpio, type); \ + } while(0) +#define gpio_intr_enable_x(gpio) \ + do { \ + if(gpio < GPIO_NUM_MAX) gpio_intr_enable(gpio); \ + } while(0) +#define gpio_pad_select_gpio_x(gpio) \ + do { \ + if(gpio < GPIO_NUM_MAX) esp_rom_gpio_pad_select_gpio(gpio); \ + } while(0) diff --git a/components/services/infrared.c b/components/services/infrared.c index 18378ebf..a08231ca 100644 --- a/components/services/infrared.c +++ b/components/services/infrared.c @@ -28,7 +28,7 @@ static int8_t ir_gpio = -1; * @brief IR device type * */ -typedef void *ir_dev_t; +typedef void* ir_dev_t; /** * @brief IR parser type @@ -53,7 +53,7 @@ struct ir_parser_s { * - ESP_ERR_INVALID_ARG: Input raw data failed because of invalid argument * - ESP_FAIL: Input raw data failed because some other error occurred */ - esp_err_t (*input)(ir_parser_t *parser, void *raw_data, uint32_t length); + esp_err_t (*input)(ir_parser_t* parser, void* raw_data, uint32_t length); /** * @brief Get the scan code after decoding of raw data @@ -68,7 +68,7 @@ struct ir_parser_s { * - ESP_ERR_INVALID_ARG: Get scan code failed because of invalid arguments * - ESP_FAIL: Get scan code failed because some error occurred */ - esp_err_t (*get_scan_code)(ir_parser_t *parser, uint32_t *address, uint32_t *command, bool *repeat); + esp_err_t (*get_scan_code)(ir_parser_t* parser, uint32_t* address, uint32_t* command, bool* repeat); }; typedef struct { @@ -77,26 +77,19 @@ typedef struct { uint32_t margin_us; /*!< Timing parameter, indicating the tolerance to environment noise */ } ir_parser_config_t; -#define IR_PARSER_DEFAULT_CONFIG(dev) \ - { \ - .dev_hdl = dev, \ - .flags = 0, \ - .margin_us = 200, \ - } +#define IR_PARSER_DEFAULT_CONFIG(dev) \ + { .dev_hdl = dev, .flags = 0, .margin_us = 200, } -ir_parser_t *ir_parser = NULL; - -#define RMT_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) +ir_parser_t* ir_parser = NULL; +#define RMT_CHECK(a, str, goto_tag, ret_value, ...) \ + do { \ + if(!(a)) { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while(0) /**************************************************************************************** * NEC protocol @@ -114,7 +107,6 @@ ir_parser_t *ir_parser = NULL; #define NEC_REPEAT_CODE_LOW_US (2250) #define NEC_ENDING_CODE_HIGH_US (560) - typedef struct { ir_parser_t parent; uint32_t flags; @@ -127,7 +119,7 @@ typedef struct { uint32_t payload_logic1_high_ticks; uint32_t payload_logic1_low_ticks; uint32_t margin_ticks; - rmt_item32_t *buffer; + rmt_item32_t* buffer; uint32_t cursor; uint32_t last_address; uint32_t last_command; @@ -145,7 +137,7 @@ static inline bool nec_check_in_range(uint32_t raw_ticks, uint32_t target_ticks, /**************************************************************************************** * */ -static bool nec_parse_head(nec_parser_t *nec_parser) { +static bool nec_parse_head(nec_parser_t* nec_parser) { nec_parser->cursor = 0; rmt_item32_t item = nec_parser->buffer[nec_parser->cursor]; bool ret = (item.level0 == nec_parser->inverse) && (item.level1 != nec_parser->inverse) && @@ -158,7 +150,7 @@ static bool nec_parse_head(nec_parser_t *nec_parser) { /**************************************************************************************** * */ -static bool nec_parse_logic0(nec_parser_t *nec_parser) { +static bool nec_parse_logic0(nec_parser_t* nec_parser) { rmt_item32_t item = nec_parser->buffer[nec_parser->cursor]; bool ret = (item.level0 == nec_parser->inverse) && (item.level1 != nec_parser->inverse) && nec_check_in_range(item.duration0, nec_parser->payload_logic0_high_ticks, nec_parser->margin_ticks) && @@ -169,7 +161,7 @@ static bool nec_parse_logic0(nec_parser_t *nec_parser) { /**************************************************************************************** * */ -static bool nec_parse_logic1(nec_parser_t *nec_parser) { +static bool nec_parse_logic1(nec_parser_t* nec_parser) { rmt_item32_t item = nec_parser->buffer[nec_parser->cursor]; bool ret = (item.level0 == nec_parser->inverse) && (item.level1 != nec_parser->inverse) && nec_check_in_range(item.duration0, nec_parser->payload_logic1_high_ticks, nec_parser->margin_ticks) && @@ -180,20 +172,18 @@ static bool nec_parse_logic1(nec_parser_t *nec_parser) { /**************************************************************************************** * */ -static esp_err_t nec_parse_logic(ir_parser_t *parser, bool *logic) { +static esp_err_t nec_parse_logic(ir_parser_t* parser, bool* logic) { esp_err_t ret = ESP_FAIL; bool logic_value = false; - nec_parser_t *nec_parser = __containerof(parser, nec_parser_t, parent); - if (nec_parse_logic0(nec_parser)) { + nec_parser_t* nec_parser = __containerof(parser, nec_parser_t, parent); + if(nec_parse_logic0(nec_parser)) { logic_value = false; ret = ESP_OK; - } else if (nec_parse_logic1(nec_parser)) { + } else if(nec_parse_logic1(nec_parser)) { logic_value = true; ret = ESP_OK; } - if (ret == ESP_OK) { - *logic = logic_value; - } + if(ret == ESP_OK) { *logic = logic_value; } nec_parser->cursor += 1; return ret; } @@ -201,7 +191,7 @@ static esp_err_t nec_parse_logic(ir_parser_t *parser, bool *logic) { /**************************************************************************************** * */ -static bool nec_parse_repeat_frame(nec_parser_t *nec_parser) { +static bool nec_parse_repeat_frame(nec_parser_t* nec_parser) { nec_parser->cursor = 0; rmt_item32_t item = nec_parser->buffer[nec_parser->cursor]; bool ret = (item.level0 == nec_parser->inverse) && (item.level1 != nec_parser->inverse) && @@ -214,15 +204,15 @@ static bool nec_parse_repeat_frame(nec_parser_t *nec_parser) { /**************************************************************************************** * */ -static esp_err_t nec_parser_input(ir_parser_t *parser, void *raw_data, uint32_t length) { +static esp_err_t nec_parser_input(ir_parser_t* parser, void* raw_data, uint32_t length) { esp_err_t ret = ESP_OK; - nec_parser_t *nec_parser = __containerof(parser, nec_parser_t, parent); + nec_parser_t* nec_parser = __containerof(parser, nec_parser_t, parent); RMT_CHECK(raw_data, "input data can't be null", err, ESP_ERR_INVALID_ARG); nec_parser->buffer = raw_data; // Data Frame costs 34 items and Repeat Frame costs 2 items - if (length == NEC_DATA_FRAME_RMT_WORDS) { + if(length == NEC_DATA_FRAME_RMT_WORDS) { nec_parser->repeat = false; - } else if (length == NEC_REPEAT_FRAME_RMT_WORDS) { + } else if(length == NEC_REPEAT_FRAME_RMT_WORDS) { nec_parser->repeat = true; } else { ret = ESP_FAIL; @@ -235,31 +225,27 @@ err: /**************************************************************************************** * */ -static esp_err_t nec_parser_get_scan_code(ir_parser_t *parser, uint32_t *address, uint32_t *command, bool *repeat) { +static esp_err_t nec_parser_get_scan_code(ir_parser_t* parser, uint32_t* address, uint32_t* command, bool* repeat) { esp_err_t ret = ESP_FAIL; uint32_t addr = 0; uint32_t cmd = 0; bool logic_value = false; - nec_parser_t *nec_parser = __containerof(parser, nec_parser_t, parent); - if (nec_parser->repeat) { - if (nec_parse_repeat_frame(nec_parser)) { + nec_parser_t* nec_parser = __containerof(parser, nec_parser_t, parent); + if(nec_parser->repeat) { + if(nec_parse_repeat_frame(nec_parser)) { *address = nec_parser->last_address; *command = nec_parser->last_command; *repeat = true; ret = ESP_OK; } } else { - if (nec_parse_head(nec_parser)) { + if(nec_parse_head(nec_parser)) { // for the forgetful, need to do a bitreverse - for (int i = 15; i >= 0; i--) { - if (nec_parse_logic(parser, &logic_value) == ESP_OK) { - addr |= (logic_value << i); - } + for(int i = 15; i >= 0; i--) { + if(nec_parse_logic(parser, &logic_value) == ESP_OK) { addr |= (logic_value << i); } } - for (int i = 15; i >= 0; i--) { - if (nec_parse_logic(parser, &logic_value) == ESP_OK) { - cmd |= (logic_value << i); - } + for(int i = 15; i >= 0; i--) { + if(nec_parse_logic(parser, &logic_value) == ESP_OK) { cmd |= (logic_value << i); } } *address = addr; *command = cmd; @@ -276,18 +262,15 @@ static esp_err_t nec_parser_get_scan_code(ir_parser_t *parser, uint32_t *address /**************************************************************************************** * */ -ir_parser_t *ir_parser_rmt_new_nec(const ir_parser_config_t *config) { - ir_parser_t *ret = NULL; - nec_parser_t *nec_parser = calloc(1, sizeof(nec_parser_t)); +ir_parser_t* ir_parser_rmt_new_nec(const ir_parser_config_t* config) { + ir_parser_t* ret = NULL; + nec_parser_t* nec_parser = calloc(1, sizeof(nec_parser_t)); nec_parser->flags = config->flags; - if (config->flags & IR_TOOLS_FLAGS_INVERSE) { - nec_parser->inverse = true; - } + if(config->flags & IR_TOOLS_FLAGS_INVERSE) { nec_parser->inverse = true; } uint32_t counter_clk_hz = 0; - RMT_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev_hdl, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); + RMT_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev_hdl, &counter_clk_hz) == ESP_OK, "get rmt counter clock failed", err, NULL); float ratio = (float)counter_clk_hz / 1e6; nec_parser->leading_code_high_ticks = (uint32_t)(ratio * NEC_LEADING_CODE_HIGH_US); nec_parser->leading_code_low_ticks = (uint32_t)(ratio * NEC_LEADING_CODE_LOW_US); @@ -308,7 +291,7 @@ err: /**************************************************************************************** * RC5 protocol ****************************************************************************************/ - + #define RC5_MAX_FRAME_RMT_WORDS (14) // S1+S2+T+ADDR(5)+CMD(6) #define RC5_PULSE_DURATION_US (889) @@ -317,7 +300,7 @@ typedef struct { uint32_t flags; uint32_t pulse_duration_ticks; uint32_t margin_ticks; - rmt_item32_t *buffer; + rmt_item32_t* buffer; uint32_t buffer_len; uint32_t last_command; uint32_t last_address; @@ -334,21 +317,19 @@ static inline bool rc5_check_in_range(uint32_t raw_ticks, uint32_t target_ticks, /**************************************************************************************** * */ -static esp_err_t rc5_parser_input(ir_parser_t *parser, void *raw_data, uint32_t length) { +static esp_err_t rc5_parser_input(ir_parser_t* parser, void* raw_data, uint32_t length) { esp_err_t ret = ESP_OK; - rc5_parser_t *rc5_parser = __containerof(parser, rc5_parser_t, parent); + rc5_parser_t* rc5_parser = __containerof(parser, rc5_parser_t, parent); rc5_parser->buffer = raw_data; rc5_parser->buffer_len = length; - if (length > RC5_MAX_FRAME_RMT_WORDS) { - ret = ESP_FAIL; - } + if(length > RC5_MAX_FRAME_RMT_WORDS) { ret = ESP_FAIL; } return ret; } /**************************************************************************************** * */ -static inline bool rc5_duration_one_unit(rc5_parser_t *rc5_parser, uint32_t duration) { +static inline bool rc5_duration_one_unit(rc5_parser_t* rc5_parser, uint32_t duration) { return (duration < (rc5_parser->pulse_duration_ticks + rc5_parser->margin_ticks)) && (duration > (rc5_parser->pulse_duration_ticks - rc5_parser->margin_ticks)); } @@ -356,7 +337,7 @@ static inline bool rc5_duration_one_unit(rc5_parser_t *rc5_parser, uint32_t dura /**************************************************************************************** * */ -static inline bool rc5_duration_two_unit(rc5_parser_t *rc5_parser, uint32_t duration) { +static inline bool rc5_duration_two_unit(rc5_parser_t* rc5_parser, uint32_t duration) { return (duration < (rc5_parser->pulse_duration_ticks * 2 + rc5_parser->margin_ticks)) && (duration > (rc5_parser->pulse_duration_ticks * 2 - rc5_parser->margin_ticks)); } @@ -364,7 +345,7 @@ static inline bool rc5_duration_two_unit(rc5_parser_t *rc5_parser, uint32_t dura /**************************************************************************************** * */ -static esp_err_t rc5_parser_get_scan_code(ir_parser_t *parser, uint32_t *address, uint32_t *command, bool *repeat) { +static esp_err_t rc5_parser_get_scan_code(ir_parser_t* parser, uint32_t* address, uint32_t* command, bool* repeat) { esp_err_t ret = ESP_FAIL; uint32_t parse_result = 0; // 32 bit is enough to hold the parse result of one RC5 frame uint32_t addr = 0; @@ -373,43 +354,35 @@ static esp_err_t rc5_parser_get_scan_code(ir_parser_t *parser, uint32_t *address bool s2 = true; bool t = false; bool exchange = false; - rc5_parser_t *rc5_parser = __containerof(parser, rc5_parser_t, parent); - for (int i = 0; i < rc5_parser->buffer_len; i++) { - if (rc5_duration_one_unit(rc5_parser, rc5_parser->buffer[i].duration0)) { + rc5_parser_t* rc5_parser = __containerof(parser, rc5_parser_t, parent); + for(int i = 0; i < rc5_parser->buffer_len; i++) { + if(rc5_duration_one_unit(rc5_parser, rc5_parser->buffer[i].duration0)) { parse_result <<= 1; parse_result |= exchange; - if (rc5_duration_two_unit(rc5_parser, rc5_parser->buffer[i].duration1)) { - exchange = !exchange; - } - } else if (rc5_duration_two_unit(rc5_parser, rc5_parser->buffer[i].duration0)) { + if(rc5_duration_two_unit(rc5_parser, rc5_parser->buffer[i].duration1)) { exchange = !exchange; } + } else if(rc5_duration_two_unit(rc5_parser, rc5_parser->buffer[i].duration0)) { parse_result <<= 1; parse_result |= rc5_parser->buffer[i].level0; parse_result <<= 1; parse_result |= !rc5_parser->buffer[i].level0; - if (rc5_duration_one_unit(rc5_parser, rc5_parser->buffer[i].duration1)) { - exchange = !exchange; - } + if(rc5_duration_one_unit(rc5_parser, rc5_parser->buffer[i].duration1)) { exchange = !exchange; } } else { goto out; } } - if (!(rc5_parser->flags & IR_TOOLS_FLAGS_INVERSE)) { - parse_result = ~parse_result; - } + if(!(rc5_parser->flags & IR_TOOLS_FLAGS_INVERSE)) { parse_result = ~parse_result; } s1 = ((parse_result & 0x2000) >> 13) & 0x01; s2 = ((parse_result & 0x1000) >> 12) & 0x01; t = ((parse_result & 0x800) >> 11) & 0x01; // Check S1, must be 1 - if (s1) { - if (!(rc5_parser->flags & IR_TOOLS_FLAGS_PROTO_EXT) && !s2) { + if(s1) { + if(!(rc5_parser->flags & IR_TOOLS_FLAGS_PROTO_EXT) && !s2) { // Not standard RC5 protocol, but S2 is 0 goto out; } addr = (parse_result & 0x7C0) >> 6; cmd = (parse_result & 0x3F); - if (!s2) { - cmd |= 1 << 6; - } + if(!s2) { cmd |= 1 << 6; } *repeat = (t == rc5_parser->last_t_bit && addr == rc5_parser->last_address && cmd == rc5_parser->last_command); *address = addr; *command = cmd; @@ -425,15 +398,14 @@ out: /**************************************************************************************** * */ -ir_parser_t *ir_parser_rmt_new_rc5(const ir_parser_config_t *config) { - ir_parser_t *ret = NULL; - rc5_parser_t *rc5_parser = calloc(1, sizeof(rc5_parser_t)); +ir_parser_t* ir_parser_rmt_new_rc5(const ir_parser_config_t* config) { + ir_parser_t* ret = NULL; + rc5_parser_t* rc5_parser = calloc(1, sizeof(rc5_parser_t)); rc5_parser->flags = config->flags; uint32_t counter_clk_hz = 0; - RMT_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev_hdl, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); + RMT_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev_hdl, &counter_clk_hz) == ESP_OK, "get rmt counter clock failed", err, NULL); float ratio = (float)counter_clk_hz / 1e6; rc5_parser->pulse_duration_ticks = (uint32_t)(ratio * RC5_PULSE_DURATION_US); rc5_parser->margin_ticks = (uint32_t)(ratio * config->margin_us); @@ -444,23 +416,22 @@ err: return ret; } - /**************************************************************************************** * */ bool infrared_receive(RingbufHandle_t rb, infrared_handler handler) { - size_t rx_size = 0; - rmt_item32_t* item = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 10 / portTICK_PERIOD_MS); + size_t rx_size = 0; + rmt_item32_t* item = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, 10 / portTICK_PERIOD_MS); bool decoded = false; - - if (item) { - uint32_t addr, cmd; + + if(item) { + uint32_t addr, cmd; bool repeat = false; - + rx_size /= 4; // one RMT = 4 Bytes - - if (ir_parser->input(ir_parser, item, rx_size) == ESP_OK) { - if (ir_parser->get_scan_code(ir_parser, &addr, &cmd, &repeat) == ESP_OK) { + + if(ir_parser->input(ir_parser, item, rx_size) == ESP_OK) { + if(ir_parser->get_scan_code(ir_parser, &addr, &cmd, &repeat) == ESP_OK) { decoded = true; handler(addr, cmd); ESP_LOGI(TAG, "Scan Code %s --- addr: 0x%04x cmd: 0x%04x", repeat ? "(repeat)" : "", addr, cmd); @@ -468,42 +439,40 @@ bool infrared_receive(RingbufHandle_t rb, infrared_handler handler) { } // if we have not decoded data but lenght is reasonnable, dump it - if (!decoded && rx_size > RC5_MAX_FRAME_RMT_WORDS) { + if(!decoded && rx_size > RC5_MAX_FRAME_RMT_WORDS) { ESP_LOGI(TAG, "can't decode IR signal of len %d", rx_size); ESP_LOG_BUFFER_HEX(TAG, item, rx_size * 4); } - // after parsing the data, return spaces to ringbuffer. - vRingbufferReturnItem(rb, (void*) item); + // after parsing the data, return spaces to ringbuffer. + vRingbufferReturnItem(rb, (void*)item); } - + return decoded; } /**************************************************************************************** * */ -int8_t infrared_gpio(void) { - return ir_gpio; -}; +int8_t infrared_gpio(void) { return ir_gpio; }; /**************************************************************************************** * */ -void infrared_init(RingbufHandle_t *rb, int gpio, infrared_mode_t mode) { +void infrared_init(RingbufHandle_t* rb, int gpio, infrared_mode_t mode) { int rmt_channel = RMT_NEXT_RX_CHANNEL(); rmt_config_t rmt_rx_config = RMT_DEFAULT_CONFIG_RX(gpio, rmt_channel); rmt_config(&rmt_rx_config); rmt_driver_install(rmt_rx_config.channel, 1000, 0); - ir_parser_config_t ir_parser_config = IR_PARSER_DEFAULT_CONFIG((ir_dev_t) rmt_rx_config.channel); + ir_parser_config_t ir_parser_config = IR_PARSER_DEFAULT_CONFIG((ir_dev_t)rmt_rx_config.channel); ir_parser_config.flags |= IR_TOOLS_FLAGS_PROTO_EXT; // Using extended IR protocols (both NEC and RC5 have extended version) ir_parser = (mode == IR_NEC) ? ir_parser_rmt_new_nec(&ir_parser_config) : ir_parser_rmt_new_rc5(&ir_parser_config); ir_gpio = gpio; - + // get RMT RX ringbuffer rmt_get_ringbuf_handle(rmt_channel, rb); rmt_rx_start(rmt_channel, 1); - + ESP_LOGI(TAG, "Starting Infrared Receiver mode %s on gpio %d and channel %d", mode == IR_NEC ? "nec" : "rc5", gpio, rmt_channel); } diff --git a/components/services/infrared.h b/components/services/infrared.h index 40bb3d76..cd0d5649 100644 --- a/components/services/infrared.h +++ b/components/services/infrared.h @@ -12,10 +12,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/ringbuf.h" -typedef enum {IR_NEC, IR_RC5} infrared_mode_t; +typedef enum { IR_NEC, IR_RC5 } infrared_mode_t; typedef void (*infrared_handler)(uint16_t addr, uint16_t cmd); bool infrared_receive(RingbufHandle_t rb, infrared_handler handler); -void infrared_init(RingbufHandle_t *rb, int gpio, infrared_mode_t mode); +void infrared_init(RingbufHandle_t* rb, int gpio, infrared_mode_t mode); int8_t infrared_gpio(void); - diff --git a/components/services/led.c b/components/services/led.c index 399836aa..44e545d9 100644 --- a/components/services/led.c +++ b/components/services/led.c @@ -51,8 +51,7 @@ static const struct rmt_led_param_s { uint32_t green, red; uint32_t (*scale)(uint32_t, uint8_t); } rmt_led_param[] = { - {sys_led_types_WS2812, 24, {{{350 / RMT_CLK, 1, 1000 / RMT_CLK, 0}}}, - {{{1000 / RMT_CLK, 1, 350 / RMT_CLK, 0}}}, 0xff0000, 0x00ff00, scale24}, + {sys_led_types_WS2812, 24, {{{350 / RMT_CLK, 1, 1000 / RMT_CLK, 0}}}, {{{1000 / RMT_CLK, 1, 350 / RMT_CLK, 0}}}, 0xff0000, 0x00ff00, scale24}, {.type = -1}}; static EXT_RAM_ATTR struct led_s { @@ -93,21 +92,20 @@ static uint32_t scale24(uint32_t color, uint8_t scale) { * */ static void set_level(struct led_s* led, bool on) { - if (led->rmt) { + if(led->rmt) { uint32_t data = on ? led->rmt->scale(led->color, led->bright) : 0; uint32_t mask = 1 << (led->rmt->bits - 1); rmt_item32_t buffer[led->rmt->bits]; - for (uint32_t bit = 0; bit < led->rmt->bits; bit++) { + for(uint32_t bit = 0; bit < led->rmt->bits; bit++) { uint32_t set = data & mask; buffer[bit] = set ? led->rmt->bit_1 : led->rmt->bit_0; mask >>= 1; } rmt_write_items(led->channel, buffer, led->rmt->bits, false); - } else if (led->bright < 0 || led->gpio >= GPIO_NUM_MAX) { + } else if(led->bright < 0 || led->gpio >= GPIO_NUM_MAX) { gpio_set_level_x(led->gpio, on ? led->color : !led->color); } else { - ledc_set_duty( - LEDC_SPEED_MODE, led->channel, on ? led->bright : (led->color ? 0 : pwm_system.max)); + ledc_set_duty(LEDC_SPEED_MODE, led->channel, on ? led->bright : (led->color ? 0 : pwm_system.max)); ledc_update_duty(LEDC_SPEED_MODE, led->channel); } } @@ -118,31 +116,29 @@ static void set_level(struct led_s* led, bool on) { static void vCallbackFunction(TimerHandle_t xTimer) { struct led_s* led = (struct led_s*)pvTimerGetTimerID(xTimer); - if (!led->timer) return; + if(!led->timer) return; led->on = !led->on; - ESP_EARLY_LOGV(TAG, "led vCallbackFunction setting gpio %d level %d (bright:%d)", led->gpio, - led->on, led->bright); + ESP_EARLY_LOGV(TAG, "led vCallbackFunction setting gpio %d level %d (bright:%d)", led->gpio, led->on, led->bright); set_level(led, led->on); // was just on for a while - if (!led->on && led->offtime == -1) return; + if(!led->on && led->offtime == -1) return; // regular blinking - xTimerChangePeriod( - xTimer, (led->on ? led->ontime : led->offtime) / portTICK_PERIOD_MS, BLOCKTIME); + xTimerChangePeriod(xTimer, (led->on ? led->ontime : led->offtime) / portTICK_PERIOD_MS, BLOCKTIME); } /**************************************************************************************** * */ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) { - if (!leds[idx].gpio || leds[idx].gpio < 0) return false; + if(!leds[idx].gpio || leds[idx].gpio < 0) return false; ESP_LOGD(TAG, "led_blink_core %d on:%d off:%d, pushed:%u", idx, ontime, offtime, pushed); - if (leds[idx].timer) { + if(leds[idx].timer) { // normal requests waits if a pop is pending - if (!pushed && leds[idx].pushed) { + if(!pushed && leds[idx].pushed) { leds[idx].pushedon = ontime; leds[idx].pushedoff = offtime; return true; @@ -151,7 +147,7 @@ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) { } // save current state if not already pushed - if (!leds[idx].pushed) { + if(!leds[idx].pushed) { leds[idx].pushedon = leds[idx].ontime; leds[idx].pushedoff = leds[idx].offtime; leds[idx].pushed = pushed; @@ -161,23 +157,22 @@ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) { leds[idx].ontime = ontime; leds[idx].offtime = offtime; - if (ontime == 0) { + if(ontime == 0) { ESP_LOGD(TAG, "led %d, setting reverse level", idx); set_level(leds + idx, false); - } else if (offtime == 0) { + } else if(offtime == 0) { ESP_LOGD(TAG, "led %d, setting level", idx); set_level(leds + idx, true); } else { - if (!leds[idx].timer) { + if(!leds[idx].timer) { ESP_LOGD(TAG, "led %d, Creating timer", idx); - leds[idx].timer = xTimerCreate("ledTimer", ontime / portTICK_PERIOD_MS, pdFALSE, - (void*)&leds[idx], vCallbackFunction); + leds[idx].timer = xTimerCreate("ledTimer", ontime / portTICK_PERIOD_MS, pdFALSE, (void*)&leds[idx], vCallbackFunction); } leds[idx].on = true; set_level(leds + idx, true); ESP_LOGD(TAG, "led %d, Setting gpio %d and starting timer", idx, leds[idx].gpio); - if (xTimerStart(leds[idx].timer, BLOCKTIME) == pdFAIL) return false; + if(xTimerStart(leds[idx].timer, BLOCKTIME) == pdFAIL) return false; } return true; @@ -187,13 +182,13 @@ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) { * */ bool led_brightness(int idx, int bright) { - if (bright > 100) bright = 100; + if(bright > 100) bright = 100; - if (leds[idx].rmt) { + if(leds[idx].rmt) { leds[idx].bright = bright; } else { leds[idx].bright = pwm_system.max * powf(bright / 100.0, 3); - if (!leds[idx].color) leds[idx].bright = pwm_system.max - leds[idx].bright; + if(!leds[idx].color) leds[idx].bright = pwm_system.max - leds[idx].bright; ledc_set_duty(LEDC_SPEED_MODE, leds[idx].channel, leds[idx].bright); ledc_update_duty(LEDC_SPEED_MODE, leds[idx].channel); @@ -206,7 +201,7 @@ bool led_brightness(int idx, int bright) { * */ bool led_unpush(int idx) { - if (!leds[idx].gpio || leds[idx].gpio < 0) return false; + if(!leds[idx].gpio || leds[idx].gpio < 0) return false; led_blink_core(idx, leds[idx].pushedon, leds[idx].pushedoff, true); leds[idx].pushed = false; @@ -218,7 +213,7 @@ bool led_unpush(int idx) { * */ int led_allocate(void) { - if (led_max < MAX_LED) return led_max++; + if(led_max < MAX_LED) return led_max++; return -1; } @@ -226,29 +221,29 @@ int led_allocate(void) { * */ bool led_config(int idx, sys_led_config* led_config) { - if (!led_config->has_gpio) { - ESP_LOGD(TAG,"No GPIO configured for %s LED",idx == LED_GREEN ? "GREEN" : "RED"); + if(!led_config->has_gpio) { + ESP_LOGD(TAG, "No GPIO configured for %s LED", idx == LED_GREEN ? "GREEN" : "RED"); return false; } - if (led_config->gpio.pin < 0) { - ESP_LOGD(TAG,"GPIO -1 ignored for %s LED",idx == LED_GREEN ? "GREEN" : "RED"); + if(led_config->gpio.pin < 0) { + ESP_LOGD(TAG, "GPIO -1 ignored for %s LED", idx == LED_GREEN ? "GREEN" : "RED"); return false; } - if (idx >= MAX_LED) return false; - if (led_config->brightness > 100) led_config->brightness = 100; + if(idx >= MAX_LED) return false; + if(led_config->brightness > 100) led_config->brightness = 100; leds[idx].gpio = led_config->gpio.pin; leds[idx].color = led_config->gpio.level; leds[idx].rmt = NULL; leds[idx].bright = -1; - if (led_config->led_type != sys_led_types_GPIO) { + if(led_config->led_type != sys_led_types_GPIO) { // first make sure we have a known addressable led - for (const struct rmt_led_param_s* p = rmt_led_param; !leds[idx].rmt && p->type >= 0; p++) - if (p->type == led_config->led_type) leds[idx].rmt = p; - if (!leds[idx].rmt) return false; + for(const struct rmt_led_param_s* p = rmt_led_param; !leds[idx].rmt && p->type >= 0; p++) + if(p->type == led_config->led_type) leds[idx].rmt = p; + if(!leds[idx].rmt) return false; - if (led_rmt_channel < 0) led_rmt_channel = RMT_NEXT_TX_CHANNEL(); + if(led_rmt_channel < 0) led_rmt_channel = RMT_NEXT_TX_CHANNEL(); leds[idx].channel = led_rmt_channel; leds[idx].bright = led_config->brightness > 0 ? led_config->brightness : 100; @@ -258,13 +253,13 @@ bool led_config(int idx, sys_led_config* led_config) { rmt_config(&config); rmt_driver_install(config.channel, 0, 0); - } else if (led_config->brightness < 0 || led_config->gpio.pin >= GPIO_NUM_MAX) { + } else if(led_config->brightness < 0 || led_config->gpio.pin >= GPIO_NUM_MAX) { gpio_pad_select_gpio_x(led_config->gpio.pin); gpio_set_direction_x(led_config->gpio.pin, GPIO_MODE_OUTPUT); } else { leds[idx].channel = pwm_system.base_channel++; leds[idx].bright = pwm_system.max * powf(led_config->brightness / 100.0, 3); - if (!led_config->gpio.level) leds[idx].bright = pwm_system.max - leds[idx].bright; + if(!led_config->gpio.level) leds[idx].bright = pwm_system.max - leds[idx].bright; ledc_channel_config_t ledc_channel = { .channel = leds[idx].channel, @@ -279,9 +274,8 @@ bool led_config(int idx, sys_led_config* led_config) { } set_level(leds + idx, false); - ESP_LOGI(TAG, "Configuring LED %s %d (on:%d rmt:%s %d%% )", idx == LED_GREEN ? "GREEN" : "RED", - led_config->gpio.pin, led_config->gpio.level, sys_led_types_name(led_config->led_type), - led_config->brightness); + ESP_LOGI(TAG, "Configuring LED %s %d (on:%d rmt:%s %d%% )", idx == LED_GREEN ? "GREEN" : "RED", led_config->gpio.pin, led_config->gpio.level, + sys_led_types_name(led_config->led_type), led_config->brightness); return true; } @@ -289,7 +283,7 @@ bool led_config(int idx, sys_led_config* led_config) { * */ static void led_suspend(void) { - ESP_LOGD(TAG,"led_suspend: turning off leds"); + ESP_LOGD(TAG, "led_suspend: turning off leds"); led_off(LED_GREEN); led_off(LED_RED); } @@ -300,27 +294,27 @@ static void led_suspend(void) { void set_led_gpio(int gpio, char* value) { struct led_config_s* config; - if (strcasestr(value, "green")) + if(strcasestr(value, "green")) config = &green; - else if (strcasestr(value, "red")) + else if(strcasestr(value, "red")) config = &red; else return; config->gpio = gpio; char* p = value; - while ((p = strchr(p, ':')) != NULL) { + while((p = strchr(p, ':')) != NULL) { p++; - if ((strcasestr(p, "ws2812")) != NULL) + if((strcasestr(p, "ws2812")) != NULL) config->type = sys_led_types_WS2812; else config->color = atoi(p); } - if (config->type != sys_led_types_GPIO) { - for (const struct rmt_led_param_s* p = rmt_led_param; p->type >= 0; p++) { - if (p->type == config->type) { - if (config == &green) + if(config->type != sys_led_types_GPIO) { + for(const struct rmt_led_param_s* p = rmt_led_param; p->type >= 0; p++) { + if(p->type == config->type) { + if(config == &green) config->color = p->green; else config->color = p->red; @@ -333,23 +327,19 @@ void set_led_gpio(int gpio, char* value) { void led_svc_init(void) { sys_gpios_config* gpios = NULL; bool found = false; - - if (!platform->has_gpios) { + + if(!platform->has_gpios) { ESP_LOGI(TAG, "No LED configured"); return; } - ESP_LOGI(TAG,"Setting up leds"); + ESP_LOGI(TAG, "Setting up leds"); gpios = &platform->gpios; - if (gpios->has_greenLED) { - found = found | led_config(LED_GREEN, &gpios->greenLED); - } - if (gpios->has_redLED) { - found = found | led_config(LED_RED, &gpios->redLED); - } - ESP_LOGD(TAG,"Done setting up leds"); + if(gpios->has_greenLED) { found = found | led_config(LED_GREEN, &gpios->greenLED); } + if(gpios->has_redLED) { found = found | led_config(LED_RED, &gpios->redLED); } + ESP_LOGD(TAG, "Done setting up leds"); // make sure we switch off all leds (useful for gpio expanders) - if (found) { - ESP_LOGD(TAG,"Switching leds off"); + if(found) { + ESP_LOGD(TAG, "Switching leds off"); services_sleep_setsuspend(led_suspend); } } diff --git a/components/services/led.h b/components/services/led.h index 2317897d..476306a3 100644 --- a/components/services/led.h +++ b/components/services/led.h @@ -15,16 +15,16 @@ #include "Config.h" enum { LED_GREEN = 0, LED_RED }; -#define led_on(idx) led_blink_core(idx, 1, 0, false) -#define led_off(idx) led_blink_core(idx, 0, 0, false) -#define led_blink(idx, on, off) led_blink_core(idx, on, off, false) -#define led_blink_pushed(idx, on, off) led_blink_core(idx, on, off, true) +#define led_on(idx) led_blink_core(idx, 1, 0, false) +#define led_off(idx) led_blink_core(idx, 0, 0, false) +#define led_blink(idx, on, off) led_blink_core(idx, on, off, false) +#define led_blink_pushed(idx, on, off) led_blink_core(idx, on, off, true) // if type is LED_GPIO then color set the GPIO logic value for "on" -bool led_config(int idx, sys_led_config * led_config); +bool led_config(int idx, sys_led_config* led_config); bool led_brightness(int idx, int percent); bool led_blink_core(int idx, int ontime, int offtime, bool push); bool led_unpush(int idx); -int led_allocate(void); +int led_allocate(void); #endif diff --git a/components/services/messaging.c b/components/services/messaging.c index 012ff6f0..f8411b8d 100644 --- a/components/services/messaging.c +++ b/components/services/messaging.c @@ -35,19 +35,15 @@ messaging_handle_t get_handle_ptr(messaging_list_t* handle) { return (messaging_ RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count) { RingbufHandle_t buf_handle = NULL; StaticRingbuffer_t* buffer_struct = malloc_init_external(sizeof(StaticRingbuffer_t)); - if (buffer_struct != NULL) { - size_t buf_size = - (size_t)(sizeof(single_message_t) + 8 + MSG_LENGTH_AVG) * - (size_t)(max_count > 0 ? max_count - : 5); // no-split buffer requires an additional 8 bytes + if(buffer_struct != NULL) { + size_t buf_size = (size_t)(sizeof(single_message_t) + 8 + MSG_LENGTH_AVG) * + (size_t)(max_count > 0 ? max_count : 5); // no-split buffer requires an additional 8 bytes buf_size = buf_size - (buf_size % 4); - uint8_t* buffer_storage = - (uint8_t*)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT); - if (buffer_storage == NULL) { + uint8_t* buffer_storage = (uint8_t*)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT); + if(buffer_storage == NULL) { ESP_LOGE(tag, "buff alloc failed"); } else { - buf_handle = xRingbufferCreateStatic( - buf_size, RINGBUF_TYPE_NOSPLIT, buffer_storage, buffer_struct); + buf_handle = xRingbufferCreateStatic(buf_size, RINGBUF_TYPE_NOSPLIT, buffer_storage, buffer_struct); } } else { ESP_LOGE(tag, "ringbuf alloc failed"); @@ -57,14 +53,14 @@ RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count) { void messaging_fill_messages(messaging_list_t* target_subscriber) { single_message_t* message = NULL; UBaseType_t uxItemsWaiting; - if (!top.buf_handle) { + if(!top.buf_handle) { ESP_LOGE(tag, "Queue initialization error!"); return; } vRingbufferGetInfo(top.buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); - for (size_t i = 0; i < uxItemsWaiting; i++) { + for(size_t i = 0; i < uxItemsWaiting; i++) { message = messaging_retrieve_message(top.buf_handle); - if (message) { + if(message) { // re-post to original queue so it is available to future subscribers messaging_post_to_queue(get_handle_ptr(&top), message, message->msg_size); // post to new subscriber @@ -75,11 +71,9 @@ void messaging_fill_messages(messaging_list_t* target_subscriber) { } messaging_handle_t messaging_register_subscriber(uint8_t max_count, char* name) { messaging_list_t* cur = ⊤ - while (cur->next) { - cur = get_struct_ptr(cur->next); - } + while(cur->next) { cur = get_struct_ptr(cur->next); } cur->next = malloc_init_external(sizeof(messaging_list_t)); - if (!cur->next) { + if(!cur->next) { ESP_LOGE(tag, "subscriber alloc failed"); return NULL; } @@ -88,16 +82,14 @@ messaging_handle_t messaging_register_subscriber(uint8_t max_count, char* name) cur->max_count = max_count; cur->subscriber_name = strdup_psram(name); cur->buf_handle = messaging_create_ring_buffer(max_count); - if (cur->buf_handle) { - messaging_fill_messages(cur); - } + if(cur->buf_handle) { messaging_fill_messages(cur); } return cur->buf_handle; } void messaging_service_init() { size_t max_count = 15; ESP_LOGI(tag, "Setting up messaging"); top.buf_handle = messaging_create_ring_buffer(max_count); - if (!top.buf_handle) { + if(!top.buf_handle) { ESP_LOGE(tag, "messaging service init failed."); } else { top.max_count = max_count; @@ -107,7 +99,7 @@ void messaging_service_init() { } const char* messaging_get_type_desc(messaging_types msg_type) { - switch (msg_type) { + switch(msg_type) { CASE_TO_STR(MESSAGING_INFO); CASE_TO_STR(MESSAGING_WARNING); CASE_TO_STR(MESSAGING_ERROR); @@ -117,7 +109,7 @@ const char* messaging_get_type_desc(messaging_types msg_type) { } } const char* messaging_get_class_desc(messaging_classes msg_class) { - switch (msg_class) { + switch(msg_class) { CASE_TO_STR(MESSAGING_CLASS_OTA); CASE_TO_STR(MESSAGING_CLASS_SYSTEM); CASE_TO_STR(MESSAGING_CLASS_STATS); @@ -136,17 +128,16 @@ cJSON* messaging_retrieve_messages(RingbufHandle_t buf_handle) { size_t item_size; UBaseType_t uxItemsWaiting; vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); - for (int i = 0; i < uxItemsWaiting; i++) { + for(int i = 0; i < uxItemsWaiting; i++) { message = (single_message_t*)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); // Check received data - if (message == NULL) { + if(message == NULL) { ESP_LOGE(tag, "received null ptr"); } else { json_message = cJSON_CreateObject(); cJSON_AddStringToObject(json_message, "message", message->message); cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type)); - cJSON_AddStringToObject( - json_message, "class", messaging_get_class_desc(message->msg_class)); + cJSON_AddStringToObject(json_message, "class", messaging_get_class_desc(message->msg_class)); cJSON_AddNumberToObject(json_message, "sent_time", message->sent_time); cJSON_AddNumberToObject(json_message, "current_time", esp_timer_get_time() / 1000); cJSON_AddItemToArray(json_messages, json_message); @@ -161,7 +152,7 @@ single_message_t* messaging_retrieve_message(RingbufHandle_t buf_handle) { size_t item_size; UBaseType_t uxItemsWaiting; vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); - if (uxItemsWaiting > 0) { + if(uxItemsWaiting > 0) { message = (single_message_t*)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); message_copy = clone_obj_psram(message, item_size); vRingbufferReturnItem(buf_handle, (void*)message); @@ -169,48 +160,42 @@ single_message_t* messaging_retrieve_message(RingbufHandle_t buf_handle) { return message_copy; } -esp_err_t messaging_post_to_queue( - messaging_handle_t subscriber_handle, single_message_t* message, size_t message_size) { +esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t* message, size_t message_size) { size_t item_size = 0; messaging_list_t* subscriber = get_struct_ptr(subscriber_handle); - if (!subscriber->buf_handle) { - ESP_LOGE( - tag, "post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name)); + if(!subscriber->buf_handle) { + ESP_LOGE(tag, "post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name)); return ESP_FAIL; } void* pItem = NULL; UBaseType_t res = pdFALSE; - while (1) { - ESP_LOGD(tag, "Attempting to reserve %d bytes for %s", message_size, - str_or_unknown(subscriber->subscriber_name)); - res = - xRingbufferSendAcquire(subscriber->buf_handle, &pItem, message_size, pdMS_TO_TICKS(50)); - if (res == pdTRUE && pItem) { + while(1) { + ESP_LOGD(tag, "Attempting to reserve %d bytes for %s", message_size, str_or_unknown(subscriber->subscriber_name)); + res = xRingbufferSendAcquire(subscriber->buf_handle, &pItem, message_size, pdMS_TO_TICKS(50)); + if(res == pdTRUE && pItem) { ESP_LOGD(tag, "Reserving complete for %s", str_or_unknown(subscriber->subscriber_name)); memcpy(pItem, message, message_size); xRingbufferSendComplete(subscriber->buf_handle, pItem); break; } ESP_LOGD(tag, "Dropping for %s", str_or_unknown(subscriber->subscriber_name)); - single_message_t* dummy = (single_message_t*)xRingbufferReceive( - subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50)); - if (dummy == NULL) { + single_message_t* dummy = (single_message_t*)xRingbufferReceive(subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50)); + if(dummy == NULL) { ESP_LOGE(tag, "Dropping message failed"); break; } else { - ESP_LOGD(tag, "Dropping message of %d bytes for %s", item_size, - str_or_unknown(subscriber->subscriber_name)); + ESP_LOGD(tag, "Dropping message of %d bytes for %s", item_size, str_or_unknown(subscriber->subscriber_name)); vRingbufferReturnItem(subscriber->buf_handle, (void*)dummy); } } - if (res != pdTRUE) { + if(res != pdTRUE) { ESP_LOGE(tag, "post to %s failed", str_or_unknown(subscriber->subscriber_name)); return ESP_FAIL; } return ESP_OK; } esp_err_t messaging_type_to_err_type(messaging_types type) { - switch (type) { + switch(type) { case MESSAGING_INFO: return ESP_LOG_INFO; break; @@ -227,16 +212,14 @@ esp_err_t messaging_type_to_err_type(messaging_types type) { return ESP_LOG_DEBUG; } -void messaging_post_message( - messaging_types type, messaging_classes msg_class, const char* fmt, ...) { +void messaging_post_message(messaging_types type, messaging_classes msg_class, const char* fmt, ...) { va_list va; va_start(va, fmt); vmessaging_post_message(type, msg_class, fmt, va); va_end(va); } -void vmessaging_post_message( - messaging_types type, messaging_classes msg_class, const char* fmt, va_list va) { +void vmessaging_post_message(messaging_types type, messaging_classes msg_class, const char* fmt, va_list va) { single_message_t* message = NULL; size_t msg_size = 0; size_t ln = 0; @@ -249,15 +232,15 @@ void vmessaging_post_message( message->type = type; message->msg_class = msg_class; message->sent_time = esp_timer_get_time() / 1000; - if (type == MESSAGING_WARNING) { + if(type == MESSAGING_WARNING) { ESP_LOGW(tag, "%s", message->message); - } else if (type == MESSAGING_ERROR) { + } else if(type == MESSAGING_ERROR) { ESP_LOGE(tag, "%s", message->message); } else { ESP_LOGD(tag, "Post: %s", message->message); } - while (cur) { + while(cur) { messaging_post_to_queue(get_handle_ptr(cur), message, msg_size); cur = get_struct_ptr(cur->next); } @@ -269,7 +252,7 @@ char* messaging_alloc_format_string(const char* fmt, ...) { va_start(va, fmt); size_t ln = vsnprintf(NULL, 0, fmt, va) + 1; char* message_txt = malloc_init_external(ln); - if (message_txt) { + if(message_txt) { vsprintf(message_txt, fmt, va); va_end(va); } else { @@ -282,7 +265,7 @@ void log_send_messaging(messaging_types msgtype, const char* fmt, ...) { va_start(va, fmt); size_t ln = vsnprintf(NULL, 0, fmt, va) + 1; char* message_txt = malloc_init_external(ln); - if (message_txt) { + if(message_txt) { vsprintf(message_txt, fmt, va); va_end(va); ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(msgtype), tag, "%s", message_txt); @@ -299,7 +282,7 @@ void cmd_send_messaging(const char* cmdname, messaging_types msgtype, const char size_t cmd_len = strlen(cmdname) + 1; size_t ln = vsnprintf(NULL, 0, fmt, va) + 1; char* message_txt = malloc_init_external(ln + cmd_len); - if (message_txt) { + if(message_txt) { strcpy(message_txt, cmdname); strcat(message_txt, "\n"); vsprintf((message_txt + cmd_len), fmt, va); diff --git a/components/services/messaging.h b/components/services/messaging.h index 941a35d7..c8251955 100644 --- a/components/services/messaging.h +++ b/components/services/messaging.h @@ -7,53 +7,45 @@ extern "C" { #endif -typedef enum { - MESSAGING_INFO, - MESSAGING_WARNING, - MESSAGING_ERROR -} messaging_types; -typedef enum { - MESSAGING_CLASS_OTA, - MESSAGING_CLASS_SYSTEM, - MESSAGING_CLASS_STATS, - MESSAGING_CLASS_CFGCMD, - MESSAGING_CLASS_BT -} messaging_classes; +typedef enum { MESSAGING_INFO, MESSAGING_WARNING, MESSAGING_ERROR } messaging_types; +typedef enum { MESSAGING_CLASS_OTA, MESSAGING_CLASS_SYSTEM, MESSAGING_CLASS_STATS, MESSAGING_CLASS_CFGCMD, MESSAGING_CLASS_BT } messaging_classes; -typedef struct messaging_list_t *messaging_handle_t; +typedef struct messaging_list_t* messaging_handle_t; typedef struct { - time_t sent_time; - messaging_types type; - messaging_classes msg_class; - size_t msg_size; - char message[]; + time_t sent_time; + messaging_types type; + messaging_classes msg_class; + size_t msg_size; + char message[]; } single_message_t; -cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle); -messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name); -esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size); -void messaging_post_message(messaging_types type,messaging_classes msg_class, const char * fmt, ...); -void vmessaging_post_message(messaging_types type,messaging_classes msg_class, const char *fmt, va_list va); -cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle); -single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle); -void log_send_messaging(messaging_types msgtype,const char *fmt, ...); -void cmd_send_messaging(const char * cmdname,messaging_types msgtype, const char *fmt, ...); +cJSON* messaging_retrieve_messages(RingbufHandle_t buf_handle); +messaging_handle_t messaging_register_subscriber(uint8_t max_count, char* name); +esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t* message, size_t message_size); +void messaging_post_message(messaging_types type, messaging_classes msg_class, const char* fmt, ...); +void vmessaging_post_message(messaging_types type, messaging_classes msg_class, const char* fmt, va_list va); +cJSON* messaging_retrieve_messages(RingbufHandle_t buf_handle); +single_message_t* messaging_retrieve_message(RingbufHandle_t buf_handle); +void log_send_messaging(messaging_types msgtype, const char* fmt, ...); +void cmd_send_messaging(const char* cmdname, messaging_types msgtype, const char* fmt, ...); esp_err_t messaging_type_to_err_type(messaging_types type); -char * messaging_alloc_format_string(const char *fmt, ...) ; +char* messaging_alloc_format_string(const char* fmt, ...); void messaging_service_init(); -#define REALLOC_CAT(e,n) e=realloc(e,strlen(n)); e=strcat(e,n) -#define LOG_SEND(y, ...) \ -{ \ -ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(y),TAG, ##__VA_ARGS__); \ -messaging_post_message(y, MESSAGING_CLASS_SYSTEM, ##__VA_ARGS__); } - -#define LOG_SEND_ERROR( ...) LOG_SEND(MESSAGING_ERROR,##__VA_ARGS__) -#define LOG_SEND_INFO( ...) LOG_SEND(MESSAGING_INFO,##__VA_ARGS__) -#define LOG_SEND_WARN( ...) LOG_SEND(MESSAGING_WARNING,##__VA_ARGS__) +#define REALLOC_CAT(e, n) \ + e = realloc(e, strlen(n)); \ + e = strcat(e, n) +#define LOG_SEND(y, ...) \ + { \ + ESP_LOG_LEVEL_LOCAL(messaging_type_to_err_type(y), TAG, ##__VA_ARGS__); \ + messaging_post_message(y, MESSAGING_CLASS_SYSTEM, ##__VA_ARGS__); \ + } +#define LOG_SEND_ERROR(...) LOG_SEND(MESSAGING_ERROR, ##__VA_ARGS__) +#define LOG_SEND_INFO(...) LOG_SEND(MESSAGING_INFO, ##__VA_ARGS__) +#define LOG_SEND_WARN(...) LOG_SEND(MESSAGING_WARNING, ##__VA_ARGS__) #ifdef __cplusplus -} +} #endif \ No newline at end of file diff --git a/components/services/monitor.c b/components/services/monitor.c index 0ff0bf97..685c4330 100644 --- a/components/services/monitor.c +++ b/components/services/monitor.c @@ -26,12 +26,12 @@ #include "cJSON.h" #include "tools.h" -#define PSEUDO_IDLE_STACK_SIZE (6*1024) +#define PSEUDO_IDLE_STACK_SIZE (6 * 1024) -#define MONITOR_TIMER (10*1000) -#define SCRATCH_SIZE 256 +#define MONITOR_TIMER (10 * 1000) +#define SCRATCH_SIZE 256 -static const char *TAG = "monitor"; +static const char* TAG = "monitor"; void (*pseudo_idle_svc)(uint32_t now); @@ -41,78 +41,77 @@ bool jack_inserted_svc(void); void (*spkfault_handler_svc)(bool inserted); bool spkfault_svc(void); - static bool monitor_stats; /**************************************************************************************** * */ -static void task_stats( cJSON* top ) { +static void task_stats(cJSON* top) { #ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY #pragma message("Compiled with trace facility") - static struct { - TaskStatus_t *tasks; - uint32_t total, n; - } current, previous; - - cJSON * tlist=cJSON_CreateArray(); - current.n = uxTaskGetNumberOfTasks(); - current.tasks = malloc_init_external( current.n * sizeof( TaskStatus_t ) ); - current.n = uxTaskGetSystemState( current.tasks, current.n, ¤t.total ); - cJSON_AddNumberToObject(top,"ntasks",current.n); + static struct { + TaskStatus_t* tasks; + uint32_t total, n; + } current, previous; - char scratch[SCRATCH_SIZE] = { }; + cJSON* tlist = cJSON_CreateArray(); + current.n = uxTaskGetNumberOfTasks(); + current.tasks = malloc_init_external(current.n * sizeof(TaskStatus_t)); + current.n = uxTaskGetSystemState(current.tasks, current.n, ¤t.total); + cJSON_AddNumberToObject(top, "ntasks", current.n); + + char scratch[SCRATCH_SIZE] = {}; #ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS #pragma message("Compiled with runtime stats") - uint32_t elapsed = current.total - previous.total; + uint32_t elapsed = current.total - previous.total; - for(int i = 0, n = 0; i < current.n; i++ ) { - for (int j = 0; j < previous.n; j++) { - if (current.tasks[i].xTaskNumber == previous.tasks[j].xTaskNumber) { - n += snprintf(scratch + n, SCRATCH_SIZE - n, "%16s (%u) %2" PRIu32 "%% s:%5" PRIu32, current.tasks[i].pcTaskName, - (unsigned) current.tasks[i].eCurrentState, - (uint32_t) (100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed), - (uint32_t) current.tasks[i].usStackHighWaterMark); - cJSON * t=cJSON_CreateObject(); - cJSON_AddNumberToObject(t,"cpu",100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed); - cJSON_AddNumberToObject(t,"minstk",current.tasks[i].usStackHighWaterMark); - cJSON_AddNumberToObject(t,"bprio",current.tasks[i].uxBasePriority); - cJSON_AddNumberToObject(t,"cprio",current.tasks[i].uxCurrentPriority); - cJSON_AddStringToObject(t,"nme",current.tasks[i].pcTaskName); - cJSON_AddNumberToObject(t,"st",current.tasks[i].eCurrentState); - cJSON_AddNumberToObject(t,"num",current.tasks[i].xTaskNumber); - cJSON_AddItemToArray(tlist,t); - if (i % 3 == 2 || i == current.n - 1) { - ESP_LOGI(TAG, "%s", scratch); - n = 0; - } - break; - } - } - } + for(int i = 0, n = 0; i < current.n; i++) { + for(int j = 0; j < previous.n; j++) { + if(current.tasks[i].xTaskNumber == previous.tasks[j].xTaskNumber) { + n += snprintf(scratch + n, SCRATCH_SIZE - n, "%16s (%u) %2" PRIu32 "%% s:%5" PRIu32, current.tasks[i].pcTaskName, + (unsigned)current.tasks[i].eCurrentState, + (uint32_t)(100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed), + (uint32_t)current.tasks[i].usStackHighWaterMark); + cJSON* t = cJSON_CreateObject(); + cJSON_AddNumberToObject(t, "cpu", 100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed); + cJSON_AddNumberToObject(t, "minstk", current.tasks[i].usStackHighWaterMark); + cJSON_AddNumberToObject(t, "bprio", current.tasks[i].uxBasePriority); + cJSON_AddNumberToObject(t, "cprio", current.tasks[i].uxCurrentPriority); + cJSON_AddStringToObject(t, "nme", current.tasks[i].pcTaskName); + cJSON_AddNumberToObject(t, "st", current.tasks[i].eCurrentState); + cJSON_AddNumberToObject(t, "num", current.tasks[i].xTaskNumber); + cJSON_AddItemToArray(tlist, t); + if(i % 3 == 2 || i == current.n - 1) { + ESP_LOGI(TAG, "%s", scratch); + n = 0; + } + break; + } + } + } #else #pragma message("Compiled WITHOUT runtime stats") - for (int i = 0, n = 0; i < current.n; i ++) { - n += sprintf(scratch + n, "%16s s:%5" PRIu32 "\t", current.tasks[i].pcTaskName, (uint32_t) current.tasks[i].usStackHighWaterMark); - cJSON * t=cJSON_CreateObject(); - cJSON_AddNumberToObject(t,"minstk",current.tasks[i].usStackHighWaterMark); - cJSON_AddNumberToObject(t,"bprio",current.tasks[i].uxBasePriority); - cJSON_AddNumberToObject(t,"cprio",current.tasks[i].uxCurrentPriority); - cJSON_AddStringToObject(t,"nme",current.tasks[i].pcTaskName); - cJSON_AddNumberToObject(t,"st",current.tasks[i].eCurrentState); - cJSON_AddNumberToObject(t,"num",current.tasks[i].xTaskNumber); - cJSON_AddItemToArray(tlist,t); - if (i % 3 == 2 || i == current.n - 1) { - ESP_LOGI(TAG, "%s", scratch); - n = 0; - } - } + for(int i = 0, n = 0; i < current.n; i++) { + n += sprintf(scratch + n, "%16s s:%5" PRIu32 "\t", current.tasks[i].pcTaskName, (uint32_t)current.tasks[i].usStackHighWaterMark); + cJSON* t = cJSON_CreateObject(); + cJSON_AddNumberToObject(t, "minstk", current.tasks[i].usStackHighWaterMark); + cJSON_AddNumberToObject(t, "bprio", current.tasks[i].uxBasePriority); + cJSON_AddNumberToObject(t, "cprio", current.tasks[i].uxCurrentPriority); + cJSON_AddStringToObject(t, "nme", current.tasks[i].pcTaskName); + cJSON_AddNumberToObject(t, "st", current.tasks[i].eCurrentState); + cJSON_AddNumberToObject(t, "num", current.tasks[i].xTaskNumber); + cJSON_AddItemToArray(tlist, t); + if(i % 3 == 2 || i == current.n - 1) { + ESP_LOGI(TAG, "%s", scratch); + n = 0; + } + } #endif - cJSON_AddItemToObject(top,"tasks",tlist); - if (previous.tasks) free(previous.tasks); - previous = current; + cJSON_AddItemToObject(top, "tasks", tlist); + if(previous.tasks) free(previous.tasks); + previous = current; #else #pragma message("Compiled WITHOUT trace facility") #endif @@ -124,82 +123,76 @@ static void task_stats( cJSON* top ) { static void monitor_trace(uint32_t now) { static uint32_t last; - if (now < last + MONITOR_TIMER) return; + if(now < last + MONITOR_TIMER) return; last = now; - cJSON * top=cJSON_CreateObject(); - cJSON_AddNumberToObject(top,"free_iram",heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); - cJSON_AddNumberToObject(top,"min_free_iram",heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL)); - cJSON_AddNumberToObject(top,"free_spiram",heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); - cJSON_AddNumberToObject(top,"min_free_spiram",heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); + cJSON* top = cJSON_CreateObject(); + cJSON_AddNumberToObject(top, "free_iram", heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); + cJSON_AddNumberToObject(top, "min_free_iram", heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL)); + cJSON_AddNumberToObject(top, "free_spiram", heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); + cJSON_AddNumberToObject(top, "min_free_spiram", heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); - ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_free_size(MALLOC_CAP_DMA), - heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); + ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); - task_stats(top); - char * top_a= cJSON_PrintUnformatted(top); - if(top_a){ - messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_STATS,top_a); - FREE_AND_NULL(top_a); - } - cJSON_Delete(top); + task_stats(top); + char* top_a = cJSON_PrintUnformatted(top); + if(top_a) { + messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_STATS, top_a); + FREE_AND_NULL(top_a); + } + cJSON_Delete(top); } /**************************************************************************************** * */ -static void jack_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) { - ESP_LOGI(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed"); - if (jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED); +static void jack_handler_default(void* id, button_event_e event, button_press_e mode, bool long_press) { + ESP_LOGI(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed"); + if(jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED); } /**************************************************************************************** * */ -bool jack_inserted_svc (void) { - sys_gpio_config * jack=NULL; - if(SYS_GPIOS_NAME(jack,jack)){ - return button_is_pressed(jack->pin, NULL); - } - return false; +bool jack_inserted_svc(void) { + sys_gpio_config* jack = NULL; + if(SYS_GPIOS_NAME(jack, jack)) { return button_is_pressed(jack->pin, NULL); } + return false; } /**************************************************************************************** * */ -static void spkfault_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) { - ESP_LOGD(TAG, "Speaker status %s", event == BUTTON_PRESSED ? "faulty" : "normal"); - if (event == BUTTON_PRESSED) led_on(LED_RED); - else led_off(LED_RED); - if (spkfault_handler_svc) (*spkfault_handler_svc)(event == BUTTON_PRESSED); +static void spkfault_handler_default(void* id, button_event_e event, button_press_e mode, bool long_press) { + ESP_LOGD(TAG, "Speaker status %s", event == BUTTON_PRESSED ? "faulty" : "normal"); + if(event == BUTTON_PRESSED) + led_on(LED_RED); + else + led_off(LED_RED); + if(spkfault_handler_svc) (*spkfault_handler_svc)(event == BUTTON_PRESSED); } /**************************************************************************************** * */ -bool spkfault_svc (void) { - sys_gpio_config * spkfault=NULL; - if(SYS_GPIOS_NAME(spkfault,spkfault)){ - return button_is_pressed(spkfault->pin, NULL); - } - return false; +bool spkfault_svc(void) { + sys_gpio_config* spkfault = NULL; + if(SYS_GPIOS_NAME(spkfault, spkfault)) { return button_is_pressed(spkfault->pin, NULL); } + return false; } /**************************************************************************************** * */ -static void pseudo_idle(void *arg) { - while (1) { +static void pseudo_idle(void* arg) { + while(1) { vTaskDelay(pdMS_TO_TICKS(1000)); uint32_t now = pdTICKS_TO_MS(xTaskGetTickCount()); - if (monitor_stats) monitor_trace(now); - if (pseudo_idle_svc) pseudo_idle_svc(now); + if(monitor_stats) monitor_trace(now); + if(pseudo_idle_svc) pseudo_idle_svc(now); } } @@ -207,31 +200,26 @@ static void pseudo_idle(void *arg) { * */ void monitor_svc_init(void) { - ESP_LOGI(TAG, "Initializing monitoring"); - sys_services_config * services = NULL; - sys_gpio_config * gpio=NULL; - if(SYS_GPIOS_NAME(jack,gpio) && gpio->pin>=0){ - ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", sys_gpio_lvl_name(gpio->level), gpio->pin); - button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1); - } - if(SYS_GPIOS_NAME(spkfault,gpio) && gpio->pin>=0){ - ESP_LOGI(TAG,"Adding speaker fault (%s) detection GPIO %d", gpio->level ? "high" : "low", gpio->pin); - button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 0, spkfault_handler_default, 0, -1); - } - // do we want stats - monitor_stats = sys_services_config(services) && services->statistics; + ESP_LOGI(TAG, "Initializing monitoring"); + sys_services_config* services = NULL; + sys_gpio_config* gpio = NULL; + if(SYS_GPIOS_NAME(jack, gpio) && gpio->pin >= 0) { + ESP_LOGI(TAG, "Adding jack (%s) detection GPIO %d", sys_gpio_lvl_name(gpio->level), gpio->pin); + button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1); + } + if(SYS_GPIOS_NAME(spkfault, gpio) && gpio->pin >= 0) { + ESP_LOGI(TAG, "Adding speaker fault (%s) detection GPIO %d", gpio->level ? "high" : "low", gpio->pin); + button_create(NULL, gpio->pin, gpio->level ? BUTTON_HIGH : BUTTON_LOW, false, 0, spkfault_handler_default, 0, -1); + } + // do we want stats + monitor_stats = sys_services_config(services) && services->statistics; - ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_free_size(MALLOC_CAP_DMA), - heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); + ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); // pseudo-idle callback => don't use FreeRTOS idle callbacks so we can block (should not but ...) - StaticTask_t* xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - static EXT_RAM_ATTR StackType_t xStack[PSEUDO_IDLE_STACK_SIZE] __attribute__ ((aligned (4))); - xTaskCreateStatic( (TaskFunction_t) pseudo_idle, "pseudo_idle", PSEUDO_IDLE_STACK_SIZE, - NULL, ESP_TASK_PRIO_MIN, xStack, xTaskBuffer ); + StaticTask_t* xTaskBuffer = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + static EXT_RAM_ATTR StackType_t xStack[PSEUDO_IDLE_STACK_SIZE] __attribute__((aligned(4))); + xTaskCreateStatic((TaskFunction_t)pseudo_idle, "pseudo_idle", PSEUDO_IDLE_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN, xStack, xTaskBuffer); } diff --git a/components/services/rotary_encoder.c b/components/services/rotary_encoder.c index 650c0206..ed65f503 100644 --- a/components/services/rotary_encoder.c +++ b/components/services/rotary_encoder.c @@ -102,52 +102,50 @@ #define TABLE_ROWS 7 -#define DIR_NONE 0x0 // No complete step yet. -#define DIR_CW 0x10 // Clockwise step. -#define DIR_CCW 0x20 // Anti-clockwise step. +#define DIR_NONE 0x0 // No complete step yet. +#define DIR_CW 0x10 // Clockwise step. +#define DIR_CCW 0x20 // Anti-clockwise step. // Create the half-step state table (emits a code at 00 and 11) -#define R_START 0x0 -#define H_CCW_BEGIN 0x1 -#define H_CW_BEGIN 0x2 -#define H_START_M 0x3 -#define H_CW_BEGIN_M 0x4 +#define R_START 0x0 +#define H_CCW_BEGIN 0x1 +#define H_CW_BEGIN 0x2 +#define H_START_M 0x3 +#define H_CW_BEGIN_M 0x4 #define H_CCW_BEGIN_M 0x5 static const uint8_t _ttable_half[TABLE_ROWS][TABLE_COLS] = { // 00 01 10 11 // BA - {H_START_M, H_CW_BEGIN, H_CCW_BEGIN, R_START}, // R_START (00) - {H_START_M | DIR_CCW, R_START, H_CCW_BEGIN, R_START}, // H_CCW_BEGIN - {H_START_M | DIR_CW, H_CW_BEGIN, R_START, R_START}, // H_CW_BEGIN - {H_START_M, H_CCW_BEGIN_M, H_CW_BEGIN_M, R_START}, // H_START_M (11) - {H_START_M, H_START_M, H_CW_BEGIN_M, R_START | DIR_CW}, // H_CW_BEGIN_M - {H_START_M, H_CCW_BEGIN_M, H_START_M, R_START | DIR_CCW}, // H_CCW_BEGIN_M + {H_START_M, H_CW_BEGIN, H_CCW_BEGIN, R_START}, // R_START (00) + {H_START_M | DIR_CCW, R_START, H_CCW_BEGIN, R_START}, // H_CCW_BEGIN + {H_START_M | DIR_CW, H_CW_BEGIN, R_START, R_START}, // H_CW_BEGIN + {H_START_M, H_CCW_BEGIN_M, H_CW_BEGIN_M, R_START}, // H_START_M (11) + {H_START_M, H_START_M, H_CW_BEGIN_M, R_START | DIR_CW}, // H_CW_BEGIN_M + {H_START_M, H_CCW_BEGIN_M, H_START_M, R_START | DIR_CCW}, // H_CCW_BEGIN_M }; // Create the full-step state table (emits a code at 00 only) -# define F_CW_FINAL 0x1 -# define F_CW_BEGIN 0x2 -# define F_CW_NEXT 0x3 -# define F_CCW_BEGIN 0x4 -# define F_CCW_FINAL 0x5 -# define F_CCW_NEXT 0x6 +#define F_CW_FINAL 0x1 +#define F_CW_BEGIN 0x2 +#define F_CW_NEXT 0x3 +#define F_CCW_BEGIN 0x4 +#define F_CCW_FINAL 0x5 +#define F_CCW_NEXT 0x6 static const uint8_t _ttable_full[TABLE_ROWS][TABLE_COLS] = { // 00 01 10 11 // BA - {R_START, F_CW_BEGIN, F_CCW_BEGIN, R_START}, // R_START - {F_CW_NEXT, R_START, F_CW_FINAL, R_START | DIR_CW}, // F_CW_FINAL - {F_CW_NEXT, F_CW_BEGIN, R_START, R_START}, // F_CW_BEGIN - {F_CW_NEXT, F_CW_BEGIN, F_CW_FINAL, R_START}, // F_CW_NEXT - {F_CCW_NEXT, R_START, F_CCW_BEGIN, R_START}, // F_CCW_BEGIN - {F_CCW_NEXT, F_CCW_FINAL, R_START, R_START | DIR_CCW}, // F_CCW_FINAL - {F_CCW_NEXT, F_CCW_FINAL, F_CCW_BEGIN, R_START}, // F_CCW_NEXT + {R_START, F_CW_BEGIN, F_CCW_BEGIN, R_START}, // R_START + {F_CW_NEXT, R_START, F_CW_FINAL, R_START | DIR_CW}, // F_CW_FINAL + {F_CW_NEXT, F_CW_BEGIN, R_START, R_START}, // F_CW_BEGIN + {F_CW_NEXT, F_CW_BEGIN, F_CW_FINAL, R_START}, // F_CW_NEXT + {F_CCW_NEXT, R_START, F_CCW_BEGIN, R_START}, // F_CCW_BEGIN + {F_CCW_NEXT, F_CCW_FINAL, R_START, R_START | DIR_CCW}, // F_CCW_FINAL + {F_CCW_NEXT, F_CCW_FINAL, F_CCW_BEGIN, R_START}, // F_CCW_NEXT }; -static uint8_t _process(rotary_encoder_info_t * info) -{ +static uint8_t _process(rotary_encoder_info_t* info) { uint8_t event = 0; - if (info != NULL) - { + if(info != NULL) { // Get state of input pins. uint8_t pin_state = (gpio_get_level_x(info->pin_b) << 1) | gpio_get_level_x(info->pin_a); @@ -160,21 +158,19 @@ static uint8_t _process(rotary_encoder_info_t * info) // Return emit bits, i.e. the generated event. event = info->table_state & 0x30; #ifdef ROTARY_ENCODER_DEBUG - ESP_EARLY_LOGD(TAG, "BA %d%d, state 0x%02x, new state 0x%02x, event 0x%02x", - pin_state >> 1, pin_state & 1, old_state, info->table_state, event); + ESP_EARLY_LOGD( + TAG, "BA %d%d, state 0x%02x, new state 0x%02x, event 0x%02x", pin_state >> 1, pin_state & 1, old_state, info->table_state, event); #endif } return event; } -static void _isr_rotenc(void * args) -{ - rotary_encoder_info_t * info = (rotary_encoder_info_t *)args; +static void _isr_rotenc(void* args) { + rotary_encoder_info_t* info = (rotary_encoder_info_t*)args; uint8_t event = _process(info); bool send_event = false; - switch (event) - { + switch(event) { case DIR_CW: ++info->state.position; info->state.direction = ROTARY_ENCODER_DIRECTION_CLOCKWISE; @@ -189,39 +185,30 @@ static void _isr_rotenc(void * args) break; } - if (send_event && info->queue) - { - rotary_encoder_event_t queue_event = - { + if(send_event && info->queue) { + rotary_encoder_event_t queue_event = { .state = - { - .position = info->state.position, - .direction = info->state.direction, - }, + { + .position = info->state.position, + .direction = info->state.direction, + }, }; - if (info->pin_a < GPIO_NUM_MAX) { - BaseType_t task_woken = pdFALSE; - xQueueOverwriteFromISR(info->queue, &queue_event, &task_woken); - if (task_woken) - { - portYIELD_FROM_ISR(); - } - } - else - { - xQueueOverwrite(info->queue, &queue_event); - } + if(info->pin_a < GPIO_NUM_MAX) { + BaseType_t task_woken = pdFALSE; + xQueueOverwriteFromISR(info->queue, &queue_event, &task_woken); + if(task_woken) { portYIELD_FROM_ISR(); } + } else { + xQueueOverwrite(info->queue, &queue_event); + } } } -esp_err_t rotary_encoder_init(rotary_encoder_info_t * info, gpio_num_t pin_a, gpio_num_t pin_b) -{ +esp_err_t rotary_encoder_init(rotary_encoder_info_t* info, gpio_num_t pin_a, gpio_num_t pin_b) { esp_err_t err = ESP_OK; - if (info) - { + if(info) { info->pin_a = pin_a; info->pin_b = pin_b; - info->table = &_ttable_full[0]; //enable_half_step ? &_ttable_half[0] : &_ttable_full[0]; + info->table = &_ttable_full[0]; //enable_half_step ? &_ttable_half[0] : &_ttable_full[0]; info->table_state = R_START; info->state.position = 0; info->state.direction = ROTARY_ENCODER_DIRECTION_NOT_SET; @@ -240,111 +227,82 @@ esp_err_t rotary_encoder_init(rotary_encoder_info_t * info, gpio_num_t pin_a, gp // install interrupt handlers gpio_isr_handler_add_x(info->pin_a, _isr_rotenc, info); gpio_isr_handler_add_x(info->pin_b, _isr_rotenc, info); - } - else - { + } else { ESP_LOGE(TAG, "info is NULL"); err = ESP_ERR_INVALID_ARG; } return err; } -esp_err_t rotary_encoder_enable_half_steps(rotary_encoder_info_t * info, bool enable) -{ +esp_err_t rotary_encoder_enable_half_steps(rotary_encoder_info_t* info, bool enable) { esp_err_t err = ESP_OK; - if (info) - { + if(info) { info->table = enable ? &_ttable_half[0] : &_ttable_full[0]; info->table_state = R_START; - } - else - { + } else { ESP_LOGE(TAG, "info is NULL"); err = ESP_ERR_INVALID_ARG; } return err; } -esp_err_t rotary_encoder_flip_direction(rotary_encoder_info_t * info) -{ +esp_err_t rotary_encoder_flip_direction(rotary_encoder_info_t* info) { esp_err_t err = ESP_OK; - if (info) - { + if(info) { gpio_num_t temp = info->pin_a; info->pin_a = info->pin_b; info->pin_b = temp; - } - else - { + } else { ESP_LOGE(TAG, "info is NULL"); err = ESP_ERR_INVALID_ARG; } return err; } -esp_err_t rotary_encoder_uninit(rotary_encoder_info_t * info) -{ +esp_err_t rotary_encoder_uninit(rotary_encoder_info_t* info) { esp_err_t err = ESP_OK; - if (info) - { + if(info) { gpio_isr_handler_remove_x(info->pin_a); gpio_isr_handler_remove_x(info->pin_b); - } - else - { + } else { ESP_LOGE(TAG, "info is NULL"); err = ESP_ERR_INVALID_ARG; } return err; } -QueueHandle_t rotary_encoder_create_queue(void) -{ - return xQueueCreate(EVENT_QUEUE_LENGTH, sizeof(rotary_encoder_event_t)); -} +QueueHandle_t rotary_encoder_create_queue(void) { return xQueueCreate(EVENT_QUEUE_LENGTH, sizeof(rotary_encoder_event_t)); } -esp_err_t rotary_encoder_set_queue(rotary_encoder_info_t * info, QueueHandle_t queue) -{ +esp_err_t rotary_encoder_set_queue(rotary_encoder_info_t* info, QueueHandle_t queue) { esp_err_t err = ESP_OK; - if (info) - { + if(info) { info->queue = queue; - } - else - { + } else { ESP_LOGE(TAG, "info is NULL"); err = ESP_ERR_INVALID_ARG; } return err; } -esp_err_t rotary_encoder_get_state(const rotary_encoder_info_t * info, rotary_encoder_state_t * state) -{ +esp_err_t rotary_encoder_get_state(const rotary_encoder_info_t* info, rotary_encoder_state_t* state) { esp_err_t err = ESP_OK; - if (info && state) - { + if(info && state) { // make a snapshot of the state state->position = info->state.position; state->direction = info->state.direction; - } - else - { + } else { ESP_LOGE(TAG, "info and/or state is NULL"); err = ESP_ERR_INVALID_ARG; } return err; } -esp_err_t rotary_encoder_reset(rotary_encoder_info_t * info) -{ +esp_err_t rotary_encoder_reset(rotary_encoder_info_t* info) { esp_err_t err = ESP_OK; - if (info) - { + if(info) { info->state.position = 0; info->state.direction = ROTARY_ENCODER_DIRECTION_NOT_SET; - } - else - { + } else { ESP_LOGE(TAG, "info is NULL"); err = ESP_ERR_INVALID_ARG; } diff --git a/components/services/rotary_encoder.h b/components/services/rotary_encoder.h index 4ff414bf..fb0b8e46 100644 --- a/components/services/rotary_encoder.h +++ b/components/services/rotary_encoder.h @@ -55,9 +55,8 @@ typedef int32_t rotary_encoder_position_t; /** * @brief Enum representing the direction of rotation. */ -typedef enum -{ - ROTARY_ENCODER_DIRECTION_NOT_SET = 0, ///< Direction not yet known (stationary since reset) +typedef enum { + ROTARY_ENCODER_DIRECTION_NOT_SET = 0, ///< Direction not yet known (stationary since reset) ROTARY_ENCODER_DIRECTION_CLOCKWISE, ROTARY_ENCODER_DIRECTION_COUNTER_CLOCKWISE, } rotary_encoder_direction_t; @@ -71,32 +70,30 @@ typedef uint8_t table_row_t[TABLE_COLS]; /** * @brief Struct represents the current state of the device in terms of incremental position and direction of last movement */ -typedef struct -{ - rotary_encoder_position_t position; ///< Numerical position since reset. This value increments on clockwise rotation, and decrements on counter-clockewise rotation. Counts full or half steps depending on mode. Set to zero on reset. - rotary_encoder_direction_t direction; ///< Direction of last movement. Set to NOT_SET on reset. +typedef struct { + rotary_encoder_position_t + position; ///< Numerical position since reset. This value increments on clockwise rotation, and decrements on counter-clockewise rotation. Counts full or half steps depending on mode. Set to zero on reset. + rotary_encoder_direction_t direction; ///< Direction of last movement. Set to NOT_SET on reset. } rotary_encoder_state_t; /** * @brief Struct carries all the information needed by this driver to manage the rotary encoder device. * The fields of this structure should not be accessed directly. */ -typedef struct -{ - gpio_num_t pin_a; ///< GPIO for Signal A from the rotary encoder device - gpio_num_t pin_b; ///< GPIO for Signal B from the rotary encoder device - QueueHandle_t queue; ///< Handle for event queue, created by ::rotary_encoder_create_queue - const table_row_t * table; ///< Pointer to active state transition table - uint8_t table_state; ///< Internal state - volatile rotary_encoder_state_t state; ///< Device state +typedef struct { + gpio_num_t pin_a; ///< GPIO for Signal A from the rotary encoder device + gpio_num_t pin_b; ///< GPIO for Signal B from the rotary encoder device + QueueHandle_t queue; ///< Handle for event queue, created by ::rotary_encoder_create_queue + const table_row_t* table; ///< Pointer to active state transition table + uint8_t table_state; ///< Internal state + volatile rotary_encoder_state_t state; ///< Device state } rotary_encoder_info_t; /** * @brief Struct represents a queued event, used to communicate current position to a waiting task */ -typedef struct -{ - rotary_encoder_state_t state; ///< The device state corresponding to this event +typedef struct { + rotary_encoder_state_t state; ///< The device state corresponding to this event } rotary_encoder_event_t; /** @@ -108,7 +105,7 @@ typedef struct * @param[in] pin_b GPIO number for rotary encoder output B. * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_init(rotary_encoder_info_t * info, gpio_num_t pin_a, gpio_num_t pin_b); +esp_err_t rotary_encoder_init(rotary_encoder_info_t* info, gpio_num_t pin_a, gpio_num_t pin_b); /** * @brief Enable half-stepping mode. This generates twice as many counted steps per rotation. @@ -116,7 +113,7 @@ esp_err_t rotary_encoder_init(rotary_encoder_info_t * info, gpio_num_t pin_a, gp * @param[in] enable If true, count half steps. If false, only count full steps. * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_enable_half_steps(rotary_encoder_info_t * info, bool enable); +esp_err_t rotary_encoder_enable_half_steps(rotary_encoder_info_t* info, bool enable); /** * @brief Reverse (flip) the sense of the direction. @@ -124,7 +121,7 @@ esp_err_t rotary_encoder_enable_half_steps(rotary_encoder_info_t * info, bool en * @param[in] info Pointer to initialised rotary encoder info structure. * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_flip_direction(rotary_encoder_info_t * info); +esp_err_t rotary_encoder_flip_direction(rotary_encoder_info_t* info); /** * @brief Remove the interrupt handlers installed by ::rotary_encoder_init. @@ -132,7 +129,7 @@ esp_err_t rotary_encoder_flip_direction(rotary_encoder_info_t * info); * @param[in] info Pointer to initialised rotary encoder info structure. * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_uninit(rotary_encoder_info_t * info); +esp_err_t rotary_encoder_uninit(rotary_encoder_info_t* info); /** * @brief Create a queue handle suitable for use as an event queue. @@ -147,7 +144,7 @@ QueueHandle_t rotary_encoder_create_queue(void); * @param[in] queue Handle to queue suitable for use as an event queue. See ::rotary_encoder_create_queue. * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_set_queue(rotary_encoder_info_t * info, QueueHandle_t queue); +esp_err_t rotary_encoder_set_queue(rotary_encoder_info_t* info, QueueHandle_t queue); /** * @brief Get the current position of the rotary encoder. @@ -155,18 +152,17 @@ esp_err_t rotary_encoder_set_queue(rotary_encoder_info_t * info, QueueHandle_t q * @param[in, out] state Pointer to an allocated rotary_encoder_state_t struct that will * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_get_state(const rotary_encoder_info_t * info, rotary_encoder_state_t * state); +esp_err_t rotary_encoder_get_state(const rotary_encoder_info_t* info, rotary_encoder_state_t* state); /** * @brief Reset the current position of the rotary encoder to zero. * @param[in] info Pointer to initialised rotary encoder info structure. * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. */ -esp_err_t rotary_encoder_reset(rotary_encoder_info_t * info); - +esp_err_t rotary_encoder_reset(rotary_encoder_info_t* info); #ifdef __cplusplus } #endif -#endif // ROTARY_ENCODER_H +#endif // ROTARY_ENCODER_H diff --git a/components/services/services.c b/components/services/services.c index e73792da..4b9935e7 100644 --- a/components/services/services.c +++ b/components/services/services.c @@ -66,19 +66,15 @@ static void deep_sleep_timer_cb(TimerHandle_t timer) { } bool are_GPIOExp_equal(const sys_exp_config* exp1, const sys_exp_config* exp2) { - if (exp1 == NULL || exp2 == NULL) { + if(exp1 == NULL || exp2 == NULL) { return false; // Safeguard against NULL pointers } // Check if model, address, and base are the same - if (exp1->model != exp2->model || exp1->addr != exp2->addr || exp1->base != exp2->base) { - return false; - } + if(exp1->model != exp2->model || exp1->addr != exp2->addr || exp1->base != exp2->base) { return false; } // Check if intr structure (pin and level) are the same - if (exp1->intr != exp2->intr) { - return false; - } + if(exp1->intr != exp2->intr) { return false; } return true; } @@ -88,21 +84,19 @@ bool sys_dev_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const sys_exp_config** pExp = (sys_exp_config**)field->pData; sys_exp_config* exp = NULL; - if (istream != NULL && field->tag == sys_dev_config_gpio_exp_tag) { + if(istream != NULL && field->tag == sys_dev_config_gpio_exp_tag) { ESP_LOGD(TAG, "Decoding GPIO Expander #%d", gpio_exp_count + 1); sys_exp_config entry = sys_exp_config_init_default; - if (!pb_decode(istream, &sys_exp_config_msg, &entry)) { - return false; - } - if (entry.model == sys_exp_models_UNSPECIFIED_EXP) { + if(!pb_decode(istream, &sys_exp_config_msg, &entry)) { return false; } + if(entry.model == sys_exp_models_UNSPECIFIED_EXP) { ESP_LOGD(TAG, "Skipping GPIO Expander model %s", sys_exp_models_name(entry.model)); return true; } // Don't add the expander if it was already decoded. This could // happen if both the configuration and the platform configuration // contain the definition. - for (int i = 0; i < gpio_exp_count; i++) { - if (are_GPIOExp_equal(&(*pExp)[i], &entry)) { + for(int i = 0; i < gpio_exp_count; i++) { + if(are_GPIOExp_equal(&(*pExp)[i], &entry)) { ESP_LOGW(TAG, "GPIO Expander entry already exists, skipping addition."); return true; // Skip adding as it already exists } @@ -118,16 +112,12 @@ bool sys_dev_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const memcpy(exp, &entry, sizeof(entry)); ESP_LOGD(TAG, "GPIO Expander #%d model %s", gpio_exp_count, sys_exp_models_name(entry.model)); - } else if (ostream != NULL && field->tag == sys_dev_config_gpio_exp_tag) { + } else if(ostream != NULL && field->tag == sys_dev_config_gpio_exp_tag) { ESP_LOGV(TAG, "Encoding %d GPIO Expanders", gpio_exp_count); - for (int i = 0; i < gpio_exp_count; i++) { - if (!pb_encode_tag_for_field(ostream, field)) { - return false; - } - if (!pb_encode_submessage(ostream, &sys_exp_config_msg, &(*pExp)[i])) { - return false; - } + for(int i = 0; i < gpio_exp_count; i++) { + if(!pb_encode_tag_for_field(ostream, field)) { return false; } + if(!pb_encode_submessage(ostream, &sys_exp_config_msg, &(*pExp)[i])) { return false; } } ESP_LOGV(TAG, "GPIO Expander encoding completed"); } @@ -137,7 +127,7 @@ bool sys_dev_config_callback(pb_istream_t* istream, pb_ostream_t* ostream, const void set_gpio_level(sys_gpio_config* gpio, const char* name, gpio_mode_t mode) { ESP_LOGI(TAG, "set GPIO %u to %s, level %d", gpio->pin, name, gpio->level); - if (gpio->pin < 0) { + if(gpio->pin < 0) { ESP_LOGW(TAG, "Invalid gpio %d for %s", gpio->pin, name); return; } @@ -150,7 +140,7 @@ void set_gpio_level(sys_gpio_config* gpio, const char* name, gpio_mode_t mode) { * */ static void sleep_gpio_handler(void* id, button_event_e event, button_press_e mode, bool long_press) { - if (event == BUTTON_PRESSED) services_sleep_activate(SLEEP_ONGPIO); + if(event == BUTTON_PRESSED) services_sleep_activate(SLEEP_ONGPIO); } /**************************************************************************************** @@ -160,41 +150,39 @@ static void sleep_timer(uint32_t now) { static EXT_RAM_ATTR uint32_t last, first; // first chain the calls to pseudo_idle function - if (sleep_context.idle_chain) sleep_context.idle_chain(now); + if(sleep_context.idle_chain) sleep_context.idle_chain(now); // we need boot time for spurious timeout calculation - if (!first) first = now; + if(!first) first = now; // only query callbacks every 30s if we have at least one sleeper - if (!*sleep_context.sleeper || now < last + 30 * 1000) return; + if(!*sleep_context.sleeper || now < last + 30 * 1000) return; last = now; // time to evaluate if we had spurious wake-up - if (sleep_context.spurious && now > sleep_context.spurious + first) { + if(sleep_context.spurious && now > sleep_context.spurious + first) { bool spurious = true; // see if at least one sleeper has been awake since we started - for (uint32_t (**sleeper)(void) = sleep_context.sleeper; *sleeper && spurious; sleeper++) { - spurious &= (*sleeper)() >= now - first; - } + for(uint32_t (**sleeper)(void) = sleep_context.sleeper; *sleeper && spurious; sleeper++) { spurious &= (*sleeper)() >= now - first; } // no activity since we woke-up, this was a spurious one - if (spurious) { + if(spurious) { ESP_LOGI(TAG, "spurious wake of %d sec, going back to sleep", (now - first) / 1000); services_sleep_activate(SLEEP_ONTIMER); } // resume normal work but we might have no "regular" inactivity delay sleep_context.spurious = 0; - if (!sleep_context.delay) *sleep_context.sleeper = NULL; + if(!sleep_context.delay) *sleep_context.sleeper = NULL; ESP_LOGI(TAG, "wake-up was not spurious after %d sec", (now - first) / 1000); } // we might be here because we are waiting for spurious - if (sleep_context.delay) { + if(sleep_context.delay) { // call all sleepers to know how long for how long they have been inactive - for (uint32_t (**sleeper)(void) = sleep_context.sleeper; sleep_context.delay && *sleeper; sleeper++) { - if ((*sleeper)() < sleep_context.delay) return; + for(uint32_t (**sleeper)(void) = sleep_context.sleeper; sleep_context.delay && *sleeper; sleeper++) { + if((*sleeper)() < sleep_context.delay) return; } // if we are here, we are ready to sleep; @@ -207,11 +195,11 @@ static void sleep_timer(uint32_t now) { */ static void sleep_battery(float level, int cells) { // chain if any - if (sleep_context.battery_chain) sleep_context.battery_chain(level, cells); + if(sleep_context.battery_chain) sleep_context.battery_chain(level, cells); // then assess if we have to stop because of low batt - if (level < sleep_context.battery_level) { - if (sleep_context.battery_count++ == 2) services_sleep_activate(SLEEP_ONBATTERY); + if(level < sleep_context.battery_level) { + if(sleep_context.battery_count++ == 2) services_sleep_activate(SLEEP_ONBATTERY); } else { sleep_context.battery_count = 0; } @@ -222,13 +210,13 @@ static void sleep_battery(float level, int cells) { */ void services_sleep_init(void) { ESP_LOGD(TAG, "Initializing sleep services"); - if (!sys_services_config_SLEEP(sleep_config)) { + if(!sys_services_config_SLEEP(sleep_config)) { ESP_LOGD(TAG, "No sleep service configured"); return; } // get the wake criteria - for (int i = 0; i < sleep_config->wake_count; i++) { - if (!rtc_gpio_is_valid_gpio(sleep_config->wake[i].pin)) { + for(int i = 0; i < sleep_config->wake_count; i++) { + if(!rtc_gpio_is_valid_gpio(sleep_config->wake[i].pin)) { ESP_LOGE(TAG, "invalid wake GPIO %d (not in RTC domain)", sleep_config->wake[i].pin); } else { sleep_context.wake_gpio |= 1LL << sleep_config->wake[i].pin; @@ -238,19 +226,19 @@ void services_sleep_init(void) { } // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can // be done - if (sleep_context.wake_gpio) { + if(sleep_context.wake_gpio) { ESP_LOGI(TAG, "Sleep wake-up gpio bitmap 0x%llx (active 0x%llx)", sleep_context.wake_gpio, sleep_context.wake_level); } // do we want battery safety sleep_context.battery_level = sleep_config->batt; - if (sleep_context.battery_level != 0.0) { + if(sleep_context.battery_level != 0.0) { sleep_context.battery_chain = battery_handler_svc; battery_handler_svc = sleep_battery; ESP_LOGI(TAG, "Sleep on battery level of %.2f", sleep_context.battery_level); } - for (int i = 0; i < sleep_config->rtc_count; i++) { - if (!rtc_gpio_is_valid_gpio(sleep_config->rtc[i].pin)) { + for(int i = 0; i < sleep_config->rtc_count; i++) { + if(!rtc_gpio_is_valid_gpio(sleep_config->rtc[i].pin)) { ESP_LOGE(TAG, "invalid rtc GPIO %d", sleep_config->rtc[i].pin); } else { sleep_context.rtc_gpio |= 1LL << sleep_config->rtc[i].pin; @@ -259,12 +247,10 @@ void services_sleep_init(void) { } // when moving to esp-idf more recent than 4.4.x, multiple gpio wake-up with level specific can // be done - if (sleep_context.rtc_gpio) { - ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level); - } + if(sleep_context.rtc_gpio) { ESP_LOGI(TAG, "RTC forced gpio bitmap 0x%llx (active 0x%llx)", sleep_context.rtc_gpio, sleep_context.rtc_level); } // get the GPIOs that activate sleep (we could check that we have a valid wake) - if (sleep_config->has_sleep && sleep_config->sleep.pin >= 0) { + if(sleep_config->has_sleep && sleep_config->sleep.pin >= 0) { ESP_LOGI(TAG, "Sleep activation gpio %d (active %d)", sleep_config->sleep.pin, sleep_config->sleep.level); button_create(NULL, sleep_config->sleep.pin, sleep_config->sleep.level ? BUTTON_HIGH : BUTTON_LOW, true, 0, sleep_gpio_handler, 0, -1); } @@ -275,22 +261,20 @@ void services_sleep_init(void) { // now check why we woke-up esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); - if (cause == ESP_SLEEP_WAKEUP_EXT0 || cause == ESP_SLEEP_WAKEUP_EXT1) { + if(cause == ESP_SLEEP_WAKEUP_EXT0 || cause == ESP_SLEEP_WAKEUP_EXT1) { ESP_LOGI(TAG, "waking-up from deep sleep with cause %d", cause); // find the type of wake-up uint64_t wake_gpio; - if (cause == ESP_SLEEP_WAKEUP_EXT0) + if(cause == ESP_SLEEP_WAKEUP_EXT0) wake_gpio = sleep_context.wake_gpio; else wake_gpio = esp_sleep_get_ext1_wakeup_status(); // we might be woken up by infrared in which case we want a short sleep - if (infrared_gpio() >= 0 && ((1LL << infrared_gpio()) & wake_gpio)) { + if(infrared_gpio() >= 0 && ((1LL << infrared_gpio()) & wake_gpio)) { sleep_context.spurious = 1; - if (sleep_config->spurious > 0) { - sleep_context.spurious = sleep_config->spurious; - } + if(sleep_config->spurious > 0) { sleep_context.spurious = sleep_config->spurious; } sleep_context.spurious *= 60 * 1000; ESP_LOGI(TAG, "spurious wake-up detection during %d sec", sleep_context.spurious / 1000); @@ -298,10 +282,10 @@ void services_sleep_init(void) { } // if we have inactivity timer (user-set or because of IR wake) then active counters - if (sleep_context.delay || sleep_context.spurious) { + if(sleep_context.delay || sleep_context.spurious) { sleep_context.idle_chain = pseudo_idle_svc; pseudo_idle_svc = sleep_timer; - if (sleep_context.delay) ESP_LOGI(TAG, "inactivity timer of %d minute(s)", sleep_context.delay / (60 * 1000)); + if(sleep_context.delay) ESP_LOGI(TAG, "inactivity timer of %d minute(s)", sleep_context.delay / (60 * 1000)); } } @@ -310,41 +294,40 @@ void services_sleep_init(void) { */ void services_sleep_activate(sleep_cause_e cause) { // call all sleep hooks that might want to do something - for (void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) - (*suspend)(); + for(void (**suspend)(void) = sleep_context.suspend; *suspend; suspend++) (*suspend)(); // isolate all possible GPIOs, except the wake-up and RTC-maintaines ones esp_sleep_config_gpio_isolate(); // keep RTC domain up if we need to maintain pull-up/down of some GPIO from RTC - if (sleep_context.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + if(sleep_context.rtc_gpio) esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); - for (int i = 0; i < GPIO_NUM_MAX; i++) { + for(int i = 0; i < GPIO_NUM_MAX; i++) { // must be a RTC GPIO - if (!rtc_gpio_is_valid_gpio(i)) continue; + if(!rtc_gpio_is_valid_gpio(i)) continue; // do we need to maintain a pull-up or down of that GPIO - if ((1LL << i) & sleep_context.rtc_gpio) { - if ((sleep_context.rtc_level >> i) & 0x01) + if((1LL << i) & sleep_context.rtc_gpio) { + if((sleep_context.rtc_level >> i) & 0x01) rtc_gpio_pullup_en(i); else rtc_gpio_pulldown_en(i); // or is this not wake-up GPIO, just isolate it - } else if (!((1LL << i) & sleep_context.wake_gpio)) { + } else if(!((1LL << i) & sleep_context.wake_gpio)) { rtc_gpio_isolate(i); } } // is there just one GPIO - if (sleep_context.wake_gpio & (sleep_context.wake_gpio - 1)) { + if(sleep_context.wake_gpio & (sleep_context.wake_gpio - 1)) { ESP_LOGI(TAG, "going to sleep cause %d, wake-up on multiple GPIO, any '1' wakes up 0x%llx", cause, sleep_context.wake_gpio); #if defined(CONFIG_IDF_TARGET_ESP32S3) && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) - if (!sleep_context.wake_level) + if(!sleep_context.wake_level) esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_LOW); else #endif esp_sleep_enable_ext1_wakeup(sleep_context.wake_gpio, ESP_EXT1_WAKEUP_ANY_HIGH); - } else if (sleep_context.wake_gpio) { + } else if(sleep_context.wake_gpio) { int gpio = __builtin_ctzll(sleep_context.wake_gpio); int level = (sleep_context.wake_level >> gpio) & 0x01; ESP_LOGI(TAG, "going to sleep cause %d, wake-up on GPIO %d level %d", cause, gpio, level); @@ -355,7 +338,7 @@ void services_sleep_activate(sleep_cause_e cause) { // we need to use a timer in case the same button is used for sleep and wake-up and it's // "pressed" vs "released" selected - if (cause == SLEEP_ONKEY) + if(cause == SLEEP_ONKEY) xTimerStart(xTimerCreate("sleepTimer", pdMS_TO_TICKS(1000), pdFALSE, NULL, deep_sleep_timer_cb), 0); else esp_deep_sleep_start(); @@ -365,8 +348,8 @@ void services_sleep_activate(sleep_cause_e cause) { * */ static void register_method(void** store, size_t size, void* method) { - for (int i = 0; i < size; i++, *store++) - if (!*store) { + for(int i = 0; i < size; i++, *store++) + if(!*store) { *store = method; return; } @@ -391,7 +374,7 @@ void services_ports_init(void) { ESP_LOGI(TAG, "Initializing ports"); gpio_install_isr_service(0); ESP_LOGD(TAG, "Checking i2c port usage"); - if (platform->dev.dac.has_i2c && platform->dev.has_i2c && platform->dev.dac.i2c.port != sys_i2c_port_UNSPECIFIED && + if(platform->dev.dac.has_i2c && platform->dev.has_i2c && platform->dev.dac.i2c.port != sys_i2c_port_UNSPECIFIED && platform->dev.dac.i2c.port == platform->dev.i2c.port) { ESP_LOGE(TAG, "Port %s is used for internal DAC use. Switching to ", sys_i2c_port_name(platform->dev.dac.i2c.port)); platform->dev.i2c.port = platform->dev.i2c.port == sys_i2c_port_PORT0 ? sys_i2c_port_PORT1 : sys_i2c_port_PORT0; @@ -403,17 +386,17 @@ void services_ports_init(void) { const i2c_config_t* i2c_config = config_i2c_get(&platform->dev.i2c); ESP_LOGD(TAG, "Stored I2C configuration [sda:%d scl:%d port:%s speed:%u]", i2c_config->sda_io_num, i2c_config->scl_io_num, sys_i2c_port_name(platform->dev.i2c.port), i2c_config->master.clk_speed); - if (i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) { + if(i2c_config->sda_io_num != -1 && i2c_config->scl_io_num != -1) { ESP_LOGI(TAG, "Configuring I2C sda:%d scl:%d port:%s speed:%u", i2c_config->sda_io_num, i2c_config->scl_io_num, sys_i2c_port_name(platform->dev.i2c.port), i2c_config->master.clk_speed); i2c_param_config(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config); - if ((err = i2c_driver_install(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config->mode, 0, 0, 0)) != ESP_OK) { + if((err = i2c_driver_install(platform->dev.i2c.port - sys_i2c_port_PORT0, i2c_config->mode, 0, 0, 0)) != ESP_OK) { ESP_LOGE(TAG, "Error setting up i2c: %s", esp_err_to_name(err)); } else { i2c_configured = true; } } else { - if (platform->dev.has_display && platform->dev.display.has_common && platform->dev.display.which_dispType == sys_display_config_i2c_tag) { + if(platform->dev.has_display && platform->dev.display.has_common && platform->dev.display.which_dispType == sys_display_config_i2c_tag) { ESP_LOGE(TAG, "I2C configuration missing for display %s", sys_display_drivers_name(platform->dev.display.common.driver)); } else { ESP_LOGI(TAG, "Shared I2C not configured"); @@ -423,15 +406,15 @@ void services_ports_init(void) { const spi_bus_config_t* spi_config = config_spi_get((spi_host_device_t*)&spi_system_host); ESP_LOGD(TAG, "Stored SPI configuration[mosi:%d miso:%d clk:%d host:%u dc:%d]", spi_config->mosi_io_num, spi_config->miso_io_num, spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio); - if (spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) { + if(spi_config->mosi_io_num != -1 && spi_config->sclk_io_num != -1) { ESP_LOGI(TAG, "Configuring SPI mosi:%d miso:%d clk:%d host:%u dc:%d", spi_config->mosi_io_num, spi_config->miso_io_num, spi_config->sclk_io_num, spi_system_host, spi_system_dc_gpio); - if ((err = spi_bus_initialize(spi_system_host, spi_config, SPI_DMA_CH_AUTO)) != ESP_OK) { + if((err = spi_bus_initialize(spi_system_host, spi_config, SPI_DMA_CH_AUTO)) != ESP_OK) { ESP_LOGE(TAG, "Error setting up SPI bus: %s", esp_err_to_name(err)); } else { spi_configured = true; } - if (spi_system_dc_gpio != -1) { + if(spi_system_dc_gpio != -1) { gpio_reset_pin(spi_system_dc_gpio); gpio_set_direction(spi_system_dc_gpio, GPIO_MODE_OUTPUT); gpio_set_level(spi_system_dc_gpio, 0); @@ -440,8 +423,7 @@ void services_ports_init(void) { } } else { spi_system_host = -1; - if (platform->dev.has_display && platform->dev.display.has_common && - platform->dev.display.common.driver != sys_display_drivers_UNSPECIFIED && + if(platform->dev.has_display && platform->dev.display.has_common && platform->dev.display.common.driver != sys_display_drivers_UNSPECIFIED && platform->dev.display.which_dispType == sys_display_config_spi_tag) { ESP_LOGE(TAG, "SPI bus configuration missing for display %s", sys_display_drivers_name(platform->dev.display.common.driver)); } else { @@ -453,7 +435,7 @@ void services_gpio_init(void) { ESP_LOGI(TAG, "Initializing GPIOs"); // set potential power GPIO on chip first in case expanders are power using these sys_gpio_config* gpio = NULL; - if (SYS_GPIOS_NAME(power, gpio) && gpio->pin >= 0) { + if(SYS_GPIOS_NAME(power, gpio) && gpio->pin >= 0) { ESP_LOGD(TAG, "Handling power gpio"); gpio->level = sys_gpio_lvl_HIGH; set_gpio_level(gpio, "power", GPIO_MODE_OUTPUT); @@ -461,7 +443,7 @@ void services_gpio_init(void) { ESP_LOGD(TAG, "No power GPIO defined"); } - if (SYS_GPIOS_NAME(GND, gpio) && gpio->pin >= 0) { + if(SYS_GPIOS_NAME(GND, gpio) && gpio->pin >= 0) { ESP_LOGD(TAG, "Handling GND gpio"); gpio->level = sys_gpio_lvl_LOW; set_gpio_level(gpio, "GND", GPIO_MODE_OUTPUT); @@ -471,11 +453,11 @@ void services_gpio_init(void) { // create GPIO expanders gpio_exp_config_t gpio_exp_config; - if (platform->has_dev && gpio_exp_count > 0 && platform->dev.gpio_exp[0].model != sys_exp_models_UNSPECIFIED_EXP) { + if(platform->has_dev && gpio_exp_count > 0 && platform->dev.gpio_exp[0].model != sys_exp_models_UNSPECIFIED_EXP) { ESP_LOGI(TAG, "Initializing %d GPIO Expander(s)", gpio_exp_count); - for (int count = 0; count < gpio_exp_count; count++) { + for(int count = 0; count < gpio_exp_count; count++) { sys_exp_config* exp = &platform->dev.gpio_exp[count]; - if (exp->model == sys_exp_models_UNSPECIFIED_EXP) { + if(exp->model == sys_exp_models_UNSPECIFIED_EXP) { ESP_LOGD(TAG, "Skipping unknown model"); continue; } @@ -484,31 +466,35 @@ void services_gpio_init(void) { gpio_exp_config.count = exp->count; gpio_exp_config.phy.addr = exp->addr; gpio_exp_config.intr = exp->intr; - if (exp->has_ena && exp->ena.pin >= 0) { + if(exp->has_ena && exp->ena.pin >= 0) { gpio_exp_config.phy.ena_pin = exp->ena.pin; gpio_exp_config.phy.ena_lvl = exp->ena.level; } - if (exp->which_ExpType == sys_exp_config_spi_tag) { - if (!spi_configured) { + if(exp->which_ExpType == sys_exp_config_spi_tag) { + if(!spi_configured) { ESP_LOGE(TAG, "SPI bus not configured for GPIO Expander index %d (%s)", count, sys_exp_models_name(exp->model)); continue; } gpio_exp_config.phy.cs_pin = exp->ExpType.spi.cs; - gpio_exp_config.phy.host = - (!platform->dev.has_spi || (platform->dev.has_spi && platform->dev.spi.host == sys_dev_common_hosts_NONE) ? sys_dev_common_hosts_Host0 : platform->dev.spi.host) - sys_dev_common_hosts_Host0; + gpio_exp_config.phy.host = (!platform->dev.has_spi || (platform->dev.has_spi && platform->dev.spi.host == sys_dev_common_hosts_NONE) + ? sys_dev_common_hosts_Host0 + : platform->dev.spi.host) - + sys_dev_common_hosts_Host0; gpio_exp_config.phy.speed = exp->ExpType.spi.speed > 0 ? exp->ExpType.spi.speed : 0; } else { - if (!i2c_configured) { + if(!i2c_configured) { ESP_LOGE(TAG, "I2C bus not configured for GPIO Expander index %d (%s)", count, sys_exp_models_name(exp->model)); continue; } - gpio_exp_config.phy.port = - ((!platform->dev.has_i2c || (platform->dev.has_i2c && platform->dev.i2c.port == sys_i2c_port_UNSPECIFIED) )? sys_dev_common_ports_SYSTEM : platform->dev.i2c.port) - sys_dev_common_ports_SYSTEM ; + gpio_exp_config.phy.port = ((!platform->dev.has_i2c || (platform->dev.has_i2c && platform->dev.i2c.port == sys_i2c_port_UNSPECIFIED)) + ? sys_dev_common_ports_SYSTEM + : platform->dev.i2c.port) - + sys_dev_common_ports_SYSTEM; } strncpy(gpio_exp_config.model, sys_exp_models_name(exp->model), sizeof(gpio_exp_config.model) - 1); gpio_exp_create(&gpio_exp_config); } - } else if (gpio_exp_count > 0) { + } else if(gpio_exp_count > 0) { ESP_LOGW(TAG, "GPIO Expander count %d but none is valid", gpio_exp_count); } } diff --git a/components/services/services.h b/components/services/services.h index b91ac3b3..6c719d91 100644 --- a/components/services/services.h +++ b/components/services/services.h @@ -7,7 +7,7 @@ * https://opensource.org/licenses/MIT * */ -#include "Config.h" +#include "Config.h" #include "driver/gpio.h" #pragma once @@ -17,4 +17,4 @@ void services_sleep_activate(sleep_cause_e cause); void services_sleep_setsuspend(void (*hook)(void)); void services_sleep_setsleeper(uint32_t (*sleeper)(void)); void services_sleep_init(void); -void set_gpio_level(sys_gpio_config*gpio,const char * name, gpio_mode_t mode); +void set_gpio_level(sys_gpio_config* gpio, const char* name, gpio_mode_t mode); diff --git a/components/services/system_time.c b/components/services/system_time.c index a04e857c..92c3c9e0 100644 --- a/components/services/system_time.c +++ b/components/services/system_time.c @@ -23,14 +23,15 @@ void system_time_init(void) { char strftime_buf[64]; time_t now; struct tm timeinfo; - const char* timezone = - platform->has_services && platform->services.timezone && strlen(platform->services.timezone) > 0 ? platform->services.timezone : "EST5EDT,M3.2.0/2,M11.1.0"; + const char* timezone = platform->has_services && platform->services.timezone && strlen(platform->services.timezone) > 0 + ? platform->services.timezone + : "EST5EDT,M3.2.0/2,M11.1.0"; setenv("TZ", timezone, 1); tzset(); time(&now); localtime_r(&now, &timeinfo); // Is time set? If not, tm_year will be (1970 - 1900). - if (timeinfo.tm_year < (2016 - 1900)) { + if(timeinfo.tm_year < (2016 - 1900)) { ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP."); sntp_servermode_dhcp(2); esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL); diff --git a/components/spotify/Shim.cpp b/components/spotify/Shim.cpp index 81d7640a..6d8bfddb 100644 --- a/components/spotify/Shim.cpp +++ b/components/spotify/Shim.cpp @@ -33,19 +33,19 @@ #include "accessors.h" #include "tools_http_utils.h" -static class cspotPlayer *player; +static class cspotPlayer* player; static const struct { - const char *ns; - const char *credentials; -} spotify_ns = { .ns = "spotify", .credentials = "credentials" }; + const char* ns; + const char* credentials; +} spotify_ns = {.ns = "spotify", .credentials = "credentials"}; /**************************************************************************************** * Player's main class & task */ class cspotPlayer : public bell::Task { -private: + private: std::string name; bell::WrappedSemaphore clientConnected; std::atomic isPaused; @@ -53,7 +53,7 @@ private: std::atomic state; std::string credentials; bool zeroConf; - + int startOffset, volume = 0, bitrate = 160; httpd_handle_t serverHandle; int serverPort; @@ -66,69 +66,59 @@ private: void eventHandler(std::unique_ptr event); void trackHandler(void); - size_t pcmWrite(uint8_t *pcm, size_t bytes, std::string_view trackId); + size_t pcmWrite(uint8_t* pcm, size_t bytes, std::string_view trackId); void enableZeroConf(void); void runTask(); - sys_spotify_config * cspot_config = NULL; + sys_spotify_config* cspot_config = NULL; -public: - typedef enum {TRACK_INIT, TRACK_NOTIFY, TRACK_STREAM, TRACK_END} TrackStatus; + public: + typedef enum { TRACK_INIT, TRACK_NOTIFY, TRACK_STREAM, TRACK_END } TrackStatus; std::atomic trackStatus = TRACK_INIT; cspotPlayer(const char*, httpd_handle_t, int, cspot_cmd_cb_t, cspot_data_cb_t); - esp_err_t handleGET(httpd_req_t *request); - esp_err_t handlePOST(httpd_req_t *request); + esp_err_t handleGET(httpd_req_t* request); + esp_err_t handlePOST(httpd_req_t* request); void command(cspot_event_t event); }; -cspotPlayer::cspotPlayer(const char* name, httpd_handle_t server, int port, cspot_cmd_cb_t cmdHandler, cspot_data_cb_t dataHandler) : - bell::Task("playerInstance", 32 * 1024, 0, 0), - serverHandle(server), serverPort(port), - cmdHandler(cmdHandler), dataHandler(dataHandler) { +cspotPlayer::cspotPlayer(const char* name, httpd_handle_t server, int port, cspot_cmd_cb_t cmdHandler, cspot_data_cb_t dataHandler) + : bell::Task("playerInstance", 32 * 1024, 0, 0), serverHandle(server), serverPort(port), cmdHandler(cmdHandler), dataHandler(dataHandler) { - if(!sys_services_config_SPOTIFY(cspot_config)){ - return; - } + if(!sys_services_config_SPOTIFY(cspot_config)) { return; } volume = cspot_config->volume; bitrate = cspot_config->bitrate; - this->name = strlen(platform->names.spotify)>0?platform->names.spotify:name; + this->name = strlen(platform->names.spotify) > 0 ? platform->names.spotify : name; zeroConf = cspot_config->zeroconf; - + // get optional credentials from own NVS - if (!zeroConf) { - if (sys_state->cspot_credentials && strlen(sys_state->cspot_credentials)>0) { - this->credentials = sys_state->cspot_credentials; - } + if(!zeroConf) { + if(sys_state->cspot_credentials && strlen(sys_state->cspot_credentials) > 0) { this->credentials = sys_state->cspot_credentials; } } - if (bitrate != 96 && bitrate != 160 && bitrate != 320) bitrate = 160; + if(bitrate != 96 && bitrate != 160 && bitrate != 320) bitrate = 160; } -size_t cspotPlayer::pcmWrite(uint8_t *pcm, size_t bytes, std::string_view trackId) { - if (lastTrackId != trackId) { +size_t cspotPlayer::pcmWrite(uint8_t* pcm, size_t bytes, std::string_view trackId) { + if(lastTrackId != trackId) { CSPOT_LOG(info, "new track started <%s> => <%s>", lastTrackId.c_str(), trackId.data()); lastTrackId = trackId; trackHandler(); } return dataHandler(pcm, bytes); -} - -extern "C" { - static esp_err_t handleGET(httpd_req_t *request) { - return player->handleGET(request); - } - - static esp_err_t handlePOST(httpd_req_t *request) { - return player->handlePOST(request); - } } -esp_err_t cspotPlayer::handleGET(httpd_req_t *request) { +extern "C" { +static esp_err_t handleGET(httpd_req_t* request) { return player->handleGET(request); } + +static esp_err_t handlePOST(httpd_req_t* request) { return player->handlePOST(request); } +} + +esp_err_t cspotPlayer::handleGET(httpd_req_t* request) { std::string body = this->blob->buildZeroconfInfo(); - if (body.size() == 0) { + if(body.size() == 0) { CSPOT_LOG(info, "cspot empty blob's body on GET"); return ESP_ERR_HTTPD_INVALID_REQ; } @@ -139,28 +129,28 @@ esp_err_t cspotPlayer::handleGET(httpd_req_t *request) { return ESP_OK; } -esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) { - cJSON* response= cJSON_CreateObject(); +esp_err_t cspotPlayer::handlePOST(httpd_req_t* request) { + cJSON* response = cJSON_CreateObject(); //see https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf - if (cmdHandler(CSPOT_BUSY)) { + if(cmdHandler(CSPOT_BUSY)) { cJSON_AddNumberToObject(response, "status", 101); cJSON_AddStringToObject(response, "statusString", "OK"); cJSON_AddNumberToObject(response, "spotifyError", 0); // get body if any (add '\0' at the end if used as string) - if (request->content_len) { - char* body = (char*) calloc(1, request->content_len + 1); + if(request->content_len) { + char* body = (char*)calloc(1, request->content_len + 1); int size = httpd_req_recv(request, body, request->content_len); // I know this is very crude and unsafe... url_decode(body); - char *key = strtok(body, "&"); + char* key = strtok(body, "&"); std::map queryMap; - while (key) { - char *value = strchr(key, '='); + while(key) { + char* value = strchr(key, '='); *value++ = '\0'; queryMap[key] = value; key = strtok(NULL, "&"); @@ -176,13 +166,13 @@ esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) { cJSON_AddNumberToObject(response, "status", 202); cJSON_AddStringToObject(response, "statusString", "ERROR-LOGIN-FAILED"); cJSON_AddNumberToObject(response, "spotifyError", 0); - + CSPOT_LOG(info, "sink is busy, can't accept request"); } - char *responseStr = cJSON_PrintUnformatted(response); + char* responseStr = cJSON_PrintUnformatted(response); cJSON_Delete(response); - + httpd_resp_set_hdr(request, "Content-type", "application/json"); esp_err_t rc = httpd_resp_send(request, responseStr, strlen(responseStr)); free(responseStr); @@ -191,7 +181,7 @@ esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) { } void cspotPlayer::eventHandler(std::unique_ptr event) { - switch (event->eventType) { + switch(event->eventType) { case cspot::SpircHandler::EventType::PLAYBACK_START: { lastTrackId.clear(); // we are not playing anymore @@ -212,8 +202,8 @@ void cspotPlayer::eventHandler(std::unique_ptr event } case cspot::SpircHandler::EventType::TRACK_INFO: { auto trackInfo = std::get(event->data); - cmdHandler(CSPOT_TRACK_INFO, trackInfo.duration, startOffset, trackInfo.artist.c_str(), - trackInfo.album.c_str(), trackInfo.name.c_str(), trackInfo.imageUrl.c_str()); + cmdHandler(CSPOT_TRACK_INFO, trackInfo.duration, startOffset, trackInfo.artist.c_str(), trackInfo.album.c_str(), trackInfo.name.c_str(), + trackInfo.imageUrl.c_str()); spirc->updatePositionMs(startOffset); startOffset = 0; break; @@ -257,10 +247,10 @@ void cspotPlayer::trackHandler(void) { } void cspotPlayer::command(cspot_event_t event) { - if (!spirc) return; + if(!spirc) return; // switch...case consume a ton of extra .rodata - switch (event) { + switch(event) { // nextSong/previousSong come back through cspot::event as a FLUSH case CSPOT_PREV: spirc->previousSong(); @@ -301,85 +291,83 @@ void cspotPlayer::command(cspot_event_t event) { break; default: break; - } + } } void cspotPlayer::enableZeroConf(void) { httpd_uri_t request = { - .uri = "/spotify_info", - .method = HTTP_GET, - .handler = ::handleGET, - .user_ctx = NULL, + .uri = "/spotify_info", + .method = HTTP_GET, + .handler = ::handleGET, + .user_ctx = NULL, }; - + // register GET and POST handler for built-in server httpd_register_uri_handler(serverHandle, &request); request.method = HTTP_POST; request.handler = ::handlePOST; httpd_register_uri_handler(serverHandle, &request); - + CSPOT_LOG(info, "ZeroConf mode (port %d)", serverPort); // Register mdns service, for spotify to find us - bell::MDNSService::registerService( blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, - { {"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"} }); + bell::MDNSService::registerService( + blob->getDeviceName(), "_spotify-connect", "_tcp", "", serverPort, {{"VERSION", "1.0"}, {"CPath", "/spotify_info"}, {"Stack", "SP"}}); } - + void cspotPlayer::runTask() { bool useZeroConf = zeroConf; - + // construct blob for that player blob = std::make_unique(name); - + CSPOT_LOG(info, "CSpot instance service name %s (id %s)", blob->getDeviceName().c_str(), blob->getDeviceId().c_str()); - - if (!zeroConf && !credentials.empty()) { + + if(!zeroConf && !credentials.empty()) { blob->loadJson(credentials); CSPOT_LOG(info, "Reusable credentials mode"); - } else { + } else { // whether we want it or not we must use ZeroConf useZeroConf = true; enableZeroConf(); } // gone with the wind... - while (1) { - if (useZeroConf) clientConnected.wait(); + while(1) { + if(useZeroConf) clientConnected.wait(); CSPOT_LOG(info, "Spotify client launched for %s", name.c_str()); auto ctx = cspot::Context::createFromBlob(blob); - if (bitrate == 320) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_320; - else if (bitrate == 96) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_96; - else ctx->config.audioFormat = AudioFormat_OGG_VORBIS_160; + if(bitrate == 320) + ctx->config.audioFormat = AudioFormat_OGG_VORBIS_320; + else if(bitrate == 96) + ctx->config.audioFormat = AudioFormat_OGG_VORBIS_96; + else + ctx->config.audioFormat = AudioFormat_OGG_VORBIS_160; ctx->session->connectWithRandomAp(); ctx->config.authData = ctx->session->authenticate(blob); // Auth successful - if (ctx->config.authData.size() > 0) { + if(ctx->config.authData.size() > 0) { // we might have been forced to use zeroConf, so store credentials and reset zeroConf usage - if (!zeroConf) { + if(!zeroConf) { useZeroConf = false; - if(system_set_string(&sys_state_data_msg,sys_state_data_cspot_credentials_tag,sys_state,credentials.c_str())){ + if(system_set_string(&sys_state_data_msg, sys_state_data_cspot_credentials_tag, sys_state, credentials.c_str())) { config_raise_state_changed(); } } spirc = std::make_unique(ctx); state = LINKED; - + // set call back to calculate a hash on trackId spirc->getTrackPlayer()->setDataCallback( - [this](uint8_t* data, size_t bytes, std::string_view trackId) { - return pcmWrite(data, bytes, trackId); - }); + [this](uint8_t* data, size_t bytes, std::string_view trackId) { return pcmWrite(data, bytes, trackId); }); // set event (PLAY, VOLUME...) handler - spirc->setEventHandler( - [this](std::unique_ptr event) { - eventHandler(std::move(event)); - }); + spirc->setEventHandler([this](std::unique_ptr event) { eventHandler(std::move(event)); }); // Start handling mercury messages ctx->session->startTask(); @@ -388,38 +376,38 @@ void cspotPlayer::runTask() { cmdHandler(CSPOT_VOLUME, volume); // exit when player has stopped (received a DISC) - while (state == LINKED) { + while(state == LINKED) { ctx->session->handlePacket(); // low-accuracy polling events - if (trackStatus == TRACK_NOTIFY) { + if(trackStatus == TRACK_NOTIFY) { // inform Spotify that next track has started (don't need to be super accurate) uint32_t started; cmdHandler(CSPOT_QUERY_STARTED, &started); - if (started) { + if(started) { CSPOT_LOG(info, "next track's audio has reached DAC"); spirc->notifyAudioReachedPlayback(); trackStatus = TRACK_STREAM; } - } else if (trackStatus == TRACK_END) { + } else if(trackStatus == TRACK_END) { // wait for end of last track uint32_t remains; cmdHandler(CSPOT_QUERY_REMAINING, &remains); - if (!remains) { + if(!remains) { CSPOT_LOG(info, "last track finished"); trackStatus = TRACK_INIT; cmdHandler(CSPOT_STOP); spirc->notifyAudioEnded(); } } - + // on disconnect, stay in the core loop unless we are in ZeroConf mode - if (state == DISCO) { + if(state == DISCO) { // update volume then cspot_config->volume = volume; config_raise_changed(false); // in ZeroConf mod, stay connected (in this loop) - if (!zeroConf) state = LINKED; + if(!zeroConf) state = LINKED; } } @@ -429,30 +417,30 @@ void cspotPlayer::runTask() { CSPOT_LOG(info, "disconnecting player %s", name.c_str()); } else { CSPOT_LOG(error, "failed authentication, forcing ZeroConf"); - if (!useZeroConf) enableZeroConf(); + if(!useZeroConf) enableZeroConf(); useZeroConf = true; } - + // we want to release memory ASAP and for sure - ctx.reset(); + ctx.reset(); } } /**************************************************************************************** * API to create and start a cspot instance */ -struct cspot_s* cspot_create(const char *name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) { - bell::setDefaultLogger(); +struct cspot_s* cspot_create(const char* name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) { + bell::setDefaultLogger(); bell::enableTimestampLogging(true); player = new cspotPlayer(name, server, port, cmd_cb, data_cb); player->startTask(); - return (cspot_s*) player; + return (cspot_s*)player; } /**************************************************************************************** * Commands sent by local buttons/actions */ -bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) { +bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void* param) { player->command(event); - return true; + return true; } diff --git a/components/spotify/cspot_private.h b/components/spotify/cspot_private.h index fb63e5f4..d8fe9e76 100644 --- a/components/spotify/cspot_private.h +++ b/components/spotify/cspot_private.h @@ -13,14 +13,12 @@ struct cspot_s; #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -struct cspot_s* cspot_create(const char *name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb); -bool cspot_cmd(struct cspot_s *ctx, cspot_event_t event, void *param); +struct cspot_s* cspot_create(const char* name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb); +bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void* param); #ifdef __cplusplus } #endif - diff --git a/components/spotify/cspot_sink.c b/components/spotify/cspot_sink.c index 791d0cd5..243b3d03 100644 --- a/components/spotify/cspot_sink.c +++ b/components/spotify/cspot_sink.c @@ -20,175 +20,175 @@ char EXT_RAM_ATTR deviceId[16]; static EXT_RAM_ATTR struct cspot_cb_s { - cspot_cmd_vcb_t cmd; - cspot_data_cb_t data; + cspot_cmd_vcb_t cmd; + cspot_data_cb_t data; } cspot_cbs; static const char TAG[] = "cspot"; -static struct cspot_s *cspot; +static struct cspot_s* cspot; static cspot_cmd_vcb_t cmd_handler_chain; static void cspot_volume_up(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_VOLUME_UP, NULL); - ESP_LOGI(TAG, "CSpot volume up"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_VOLUME_UP, NULL); + ESP_LOGI(TAG, "CSpot volume up"); } static void cspot_volume_down(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_VOLUME_DOWN, NULL); - ESP_LOGI(TAG, "CSpot volume down"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_VOLUME_DOWN, NULL); + ESP_LOGI(TAG, "CSpot volume down"); } static void cspot_toggle(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_TOGGLE, NULL); - ESP_LOGI(TAG, "CSpot play/pause"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_TOGGLE, NULL); + ESP_LOGI(TAG, "CSpot play/pause"); } static void cspot_pause(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_PAUSE, NULL); - ESP_LOGI(TAG, "CSpot pause"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_PAUSE, NULL); + ESP_LOGI(TAG, "CSpot pause"); } static void cspot_play(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_PLAY, NULL); - ESP_LOGI(TAG, "CSpot play"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_PLAY, NULL); + ESP_LOGI(TAG, "CSpot play"); } static void cspot_stop(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_STOP, NULL); - ESP_LOGI(TAG, "CSpot stop"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_STOP, NULL); + ESP_LOGI(TAG, "CSpot stop"); } static void cspot_prev(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_PREV, NULL); - ESP_LOGI(TAG, "CSpot previous"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_PREV, NULL); + ESP_LOGI(TAG, "CSpot previous"); } static void cspot_next(bool pressed) { - if (!pressed) return; - cspot_cmd(cspot, CSPOT_NEXT, NULL); - ESP_LOGI(TAG, "CSpot next"); + if(!pressed) return; + cspot_cmd(cspot, CSPOT_NEXT, NULL); + ESP_LOGI(TAG, "CSpot next"); } const static actrls_t controls = { - NULL, // power - cspot_volume_up, cspot_volume_down, // volume up, volume down - cspot_toggle, cspot_play, // toggle, play - cspot_pause, cspot_stop, // pause, stop - NULL, NULL, // rew, fwd - cspot_prev, cspot_next, // prev, next - NULL, NULL, NULL, NULL, // left, right, up, down - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 - cspot_volume_down, cspot_volume_up, cspot_toggle// knob left, knob_right, knob push + NULL, // power + cspot_volume_up, cspot_volume_down, // volume up, volume down + cspot_toggle, cspot_play, // toggle, play + cspot_pause, cspot_stop, // pause, stop + NULL, NULL, // rew, fwd + cspot_prev, cspot_next, // prev, next + NULL, NULL, NULL, NULL, // left, right, up, down + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // pre1-10 + cspot_volume_down, cspot_volume_up, cspot_toggle // knob left, knob_right, knob push }; /**************************************************************************************** * Download callback */ -void got_artwork(uint8_t* data, size_t len, void *context) { - if (data) { - ESP_LOGI(TAG, "got artwork of %zu bytes", len); - displayer_artwork(data); - free(data); - } else { - ESP_LOGW(TAG, "artwork error or too large %zu", len); - } +void got_artwork(uint8_t* data, size_t len, void* context) { + if(data) { + ESP_LOGI(TAG, "got artwork of %zu bytes", len); + displayer_artwork(data); + free(data); + } else { + ESP_LOGW(TAG, "artwork error or too large %zu", len); + } } /**************************************************************************************** * Command handler */ static bool cmd_handler(cspot_event_t event, ...) { - va_list args; + va_list args; - va_start(args, event); - - // handle audio event and stop if forbidden - if (!cmd_handler_chain(event, args)) { - va_end(args); - return false; - } + va_start(args, event); - // now handle events for display - switch(event) { - case CSPOT_START: - actrls_set(controls, false, NULL, actrls_ir_action); - displayer_control(DISPLAYER_ACTIVATE, "SPOTIFY", true); - break; - case CSPOT_PLAY: - displayer_control(DISPLAYER_TIMER_RUN); - break; - case CSPOT_PAUSE: - displayer_control(DISPLAYER_TIMER_PAUSE); - break; - case CSPOT_DISC: - actrls_unset(); - displayer_control(DISPLAYER_SUSPEND); - break; - case CSPOT_SEEK: - displayer_timer(DISPLAYER_ELAPSED, va_arg(args, int), -1); - break; - case CSPOT_TRACK_INFO: { - uint32_t duration = va_arg(args, int), offset = va_arg(args, int); - char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*), *artwork = va_arg(args, char*); - if (artwork && displayer_can_artwork()) { - ESP_LOGI(TAG, "requesting artwork %s", artwork); - http_download(artwork, 128*1024, got_artwork, NULL); - } - displayer_metadata(artist, album, title); - displayer_timer(DISPLAYER_ELAPSED, offset, duration); - break; - } - // nothing to do on CSPOT_FLUSH - default: - break; - } - - va_end(args); - - return true; + // handle audio event and stop if forbidden + if(!cmd_handler_chain(event, args)) { + va_end(args); + return false; + } + + // now handle events for display + switch(event) { + case CSPOT_START: + actrls_set(controls, false, NULL, actrls_ir_action); + displayer_control(DISPLAYER_ACTIVATE, "SPOTIFY", true); + break; + case CSPOT_PLAY: + displayer_control(DISPLAYER_TIMER_RUN); + break; + case CSPOT_PAUSE: + displayer_control(DISPLAYER_TIMER_PAUSE); + break; + case CSPOT_DISC: + actrls_unset(); + displayer_control(DISPLAYER_SUSPEND); + break; + case CSPOT_SEEK: + displayer_timer(DISPLAYER_ELAPSED, va_arg(args, int), -1); + break; + case CSPOT_TRACK_INFO: { + uint32_t duration = va_arg(args, int), offset = va_arg(args, int); + char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*), *artwork = va_arg(args, char*); + if(artwork && displayer_can_artwork()) { + ESP_LOGI(TAG, "requesting artwork %s", artwork); + http_download(artwork, 128 * 1024, got_artwork, NULL); + } + displayer_metadata(artist, album, title); + displayer_timer(DISPLAYER_ELAPSED, offset, duration); + break; + } + // nothing to do on CSPOT_FLUSH + default: + break; + } + + va_end(args); + + return true; } /**************************************************************************************** * CSpot sink startup */ static void cspot_sink_start(nm_state_t state_id, int sub_state) { - const char *hostname; + const char* hostname; + + cmd_handler_chain = cspot_cbs.cmd; + network_get_hostname(&hostname); + + ESP_LOGI(TAG, "starting Spotify on host %s", hostname); - cmd_handler_chain = cspot_cbs.cmd; - network_get_hostname(&hostname); - - ESP_LOGI(TAG, "starting Spotify on host %s", hostname); - int port; httpd_handle_t server = http_get_server(&port); - - cspot = cspot_create(hostname, server, port, cmd_handler, cspot_cbs.data); + + cspot = cspot_create(hostname, server, port, cmd_handler, cspot_cbs.data); } /**************************************************************************************** * CSpot sink initialization */ void cspot_sink_init(cspot_cmd_vcb_t cmd_cb, cspot_data_cb_t data_cb) { - cspot_cbs.cmd = cmd_cb; - cspot_cbs.data = data_cb; + cspot_cbs.cmd = cmd_cb; + cspot_cbs.data = data_cb; - network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_CONNECTED_STATE, "cspot_sink_start", cspot_sink_start); - network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_CONNECTED_STATE, "cspot_sink_start", cspot_sink_start); + network_register_state_callback(NETWORK_WIFI_ACTIVE_STATE, WIFI_CONNECTED_STATE, "cspot_sink_start", cspot_sink_start); + network_register_state_callback(NETWORK_ETH_ACTIVE_STATE, ETH_ACTIVE_CONNECTED_STATE, "cspot_sink_start", cspot_sink_start); } /**************************************************************************************** * CSpot forced disconnection */ void cspot_disconnect(void) { - ESP_LOGI(TAG, "forced disconnection"); - displayer_control(DISPLAYER_SHUTDOWN); - cspot_cmd(cspot, CSPOT_DISC, NULL); - actrls_unset(); + ESP_LOGI(TAG, "forced disconnection"); + displayer_control(DISPLAYER_SHUTDOWN); + cspot_cmd(cspot, CSPOT_DISC, NULL); + actrls_unset(); } diff --git a/components/spotify/cspot_sink.h b/components/spotify/cspot_sink.h index 790c302a..799c491a 100644 --- a/components/spotify/cspot_sink.h +++ b/components/spotify/cspot_sink.h @@ -11,21 +11,34 @@ #include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif // STOP means remove playlist, FLUSH means flush audio buffer, DISC means bye-bye -typedef enum { CSPOT_START, CSPOT_DISC, CSPOT_FLUSH, CSPOT_STOP, CSPOT_PLAY, CSPOT_PAUSE, CSPOT_SEEK, - CSPOT_NEXT, CSPOT_PREV, CSPOT_TOGGLE, - CSPOT_TRACK_INFO, CSPOT_TRACK_MARK, - CSPOT_VOLUME, CSPOT_VOLUME_UP, CSPOT_VOLUME_DOWN, - CSPOT_BUSY, CSPOT_QUERY_STARTED, CSPOT_QUERY_REMAINING, +typedef enum { + CSPOT_START, + CSPOT_DISC, + CSPOT_FLUSH, + CSPOT_STOP, + CSPOT_PLAY, + CSPOT_PAUSE, + CSPOT_SEEK, + CSPOT_NEXT, + CSPOT_PREV, + CSPOT_TOGGLE, + CSPOT_TRACK_INFO, + CSPOT_TRACK_MARK, + CSPOT_VOLUME, + CSPOT_VOLUME_UP, + CSPOT_VOLUME_DOWN, + CSPOT_BUSY, + CSPOT_QUERY_STARTED, + CSPOT_QUERY_REMAINING, } cspot_event_t; - -typedef bool (*cspot_cmd_cb_t)(cspot_event_t event, ...); + +typedef bool (*cspot_cmd_cb_t)(cspot_event_t event, ...); typedef bool (*cspot_cmd_vcb_t)(cspot_event_t event, va_list args); -typedef uint32_t (*cspot_data_cb_t)(const uint8_t *data, size_t len); +typedef uint32_t (*cspot_data_cb_t)(const uint8_t* data, size_t len); /** * @brief init sink mode (need to be provided) diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index 01f62686..4ffbc44c 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -42,7 +42,8 @@ #include "tools.h" #include "bootstate.h" -#define IF_DISPLAY(x) if(display) { x; } +#define IF_DISPLAY(x) \ + if(display) { x; } #ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 #define OTA_CORE 0 @@ -50,272 +51,251 @@ #define OTA_CORE 1 #endif -static const char *TAG = "squeezelite-ota"; +static const char* TAG = "squeezelite-ota"; esp_http_client_handle_t ota_http_client = NULL; #define IMAGE_HEADER_SIZE sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t) + 1 #define BUFFSIZE 4096 #define HASH_LEN 32 /* SHA-256 digest length */ -typedef struct { - char * url; - char * bin; - uint32_t length; -} ota_thread_parms_t ; +typedef struct { + char* url; + char* bin; + uint32_t length; +} ota_thread_parms_t; static ota_thread_parms_t ota_thread_parms; -typedef enum { - OTA_TYPE_HTTP, - OTA_TYPE_BUFFER, - OTA_TYPE_INVALID -} ota_type_t; +typedef enum { OTA_TYPE_HTTP, OTA_TYPE_BUFFER, OTA_TYPE_INVALID } ota_type_t; -typedef struct { - size_t actual_image_len; - float downloaded_image_len; - float total_image_len; - float remain_image_len; - ota_type_t ota_type; - char * ota_write_data; - char * bin_data; - bool bOTAStarted; - size_t buffer_size; - uint8_t lastpct; - uint8_t newpct; - uint8_t newdownloadpct; - struct timeval OTA_start; - bool bOTAThreadStarted; - const esp_partition_t *configured; - const esp_partition_t *running; - const esp_partition_t * update_partition; - const esp_partition_t* last_invalid_app ; - const esp_partition_t * ota_partition; +typedef struct { + size_t actual_image_len; + float downloaded_image_len; + float total_image_len; + float remain_image_len; + ota_type_t ota_type; + char* ota_write_data; + char* bin_data; + bool bOTAStarted; + size_t buffer_size; + uint8_t lastpct; + uint8_t newpct; + uint8_t newdownloadpct; + struct timeval OTA_start; + bool bOTAThreadStarted; + const esp_partition_t* configured; + const esp_partition_t* running; + const esp_partition_t* update_partition; + const esp_partition_t* last_invalid_app; + const esp_partition_t* ota_partition; } ota_status_t; -ota_status_t * ota_status; +ota_status_t* ota_status; struct timeval tv; static esp_http_client_config_t http_client_config; - -void _printMemStats(){ - ESP_LOGD(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_free_size(MALLOC_CAP_DMA), - heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); +void _printMemStats() { + ESP_LOGD(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); } -uint8_t ota_get_pct_complete(){ - return ota_status->total_image_len==0?0: - (uint8_t)((float)ota_status->actual_image_len/ota_status->total_image_len*100.0f); +uint8_t ota_get_pct_complete() { + return ota_status->total_image_len == 0 ? 0 : (uint8_t)((float)ota_status->actual_image_len / ota_status->total_image_len * 100.0f); } -uint8_t ota_get_pct_downloaded(){ - return ota_status->total_image_len==0?0: - (uint8_t)(ota_status->downloaded_image_len/ota_status->total_image_len*100.0f); +uint8_t ota_get_pct_downloaded() { + return ota_status->total_image_len == 0 ? 0 : (uint8_t)(ota_status->downloaded_image_len / ota_status->total_image_len * 100.0f); } -typedef struct { - int x1,y1,x2,y2,width,height; +typedef struct { + int x1, y1, x2, y2, width, height; } rect_t; typedef struct _progress { - int border_thickness; - int sides_margin; - int vertical_margin; - int bar_tot_height; - int bar_fill_height; - rect_t border; - rect_t filler; + int border_thickness; + int sides_margin; + int vertical_margin; + int bar_tot_height; + int bar_fill_height; + rect_t border; + rect_t filler; } progress_t; -static progress_t * loc_displayer_get_progress_dft(){ - - int start_coord_offset=0; - static progress_t def={ - .border_thickness = 2, - .sides_margin = 2, - .bar_tot_height = 7, - }; - def.bar_fill_height= def.bar_tot_height-(def.border_thickness*2); - def.border.x1=start_coord_offset+def.sides_margin; - IF_DISPLAY(def.border.x2=GDS_GetWidth(display)-def.sides_margin); - // progress bar will be drawn at the bottom of the display - IF_DISPLAY( def.border.y2= GDS_GetHeight(display)-def.border_thickness); - def.border.y1= def.border.y2-def.bar_tot_height; - def.border.width=def.border.x2-def.border.x1; - def.border.height=def.border.y2-def.border.y1; - def.filler.x1= def.border.x1+def.border_thickness; - def.filler.x2= def.border.x2-def.border_thickness; - def.filler.y1= def.border.y1+def.border_thickness; - def.filler.y2= def.border.y2-def.border_thickness; - def.filler.width=def.filler.x2-def.filler.x1; - def.filler.height=def.filler.y2-def.filler.y1; - assert(def.filler.width>0); - assert(def.filler.height>0); - assert(def.border.width>0); - assert(def.border.height>0); - assert(def.border.width>def.filler.width); - assert(def.border.height>def.filler.height); - return &def; +static progress_t* loc_displayer_get_progress_dft() { + int start_coord_offset = 0; + static progress_t def = { + .border_thickness = 2, + .sides_margin = 2, + .bar_tot_height = 7, + }; + def.bar_fill_height = def.bar_tot_height - (def.border_thickness * 2); + def.border.x1 = start_coord_offset + def.sides_margin; + IF_DISPLAY(def.border.x2 = GDS_GetWidth(display) - def.sides_margin); + // progress bar will be drawn at the bottom of the display + IF_DISPLAY(def.border.y2 = GDS_GetHeight(display) - def.border_thickness); + def.border.y1 = def.border.y2 - def.bar_tot_height; + def.border.width = def.border.x2 - def.border.x1; + def.border.height = def.border.y2 - def.border.y1; + def.filler.x1 = def.border.x1 + def.border_thickness; + def.filler.x2 = def.border.x2 - def.border_thickness; + def.filler.y1 = def.border.y1 + def.border_thickness; + def.filler.y2 = def.border.y2 - def.border_thickness; + def.filler.width = def.filler.x2 - def.filler.x1; + def.filler.height = def.filler.y2 - def.filler.y1; + assert(def.filler.width > 0); + assert(def.filler.height > 0); + assert(def.border.width > 0); + assert(def.border.height > 0); + assert(def.border.width > def.filler.width); + assert(def.border.height > def.filler.height); + return &def; } -static void loc_displayer_progressbar(uint8_t pct){ - static progress_t * progress_coordinates; - if(display) { - if(!progress_coordinates) progress_coordinates = loc_displayer_get_progress_dft(); - int filler_x=progress_coordinates->filler.x1+(int)((float)progress_coordinates->filler.width*(float)pct/(float)100); +static void loc_displayer_progressbar(uint8_t pct) { + static progress_t* progress_coordinates; + if(display) { + if(!progress_coordinates) progress_coordinates = loc_displayer_get_progress_dft(); + int filler_x = progress_coordinates->filler.x1 + (int)((float)progress_coordinates->filler.width * (float)pct / (float)100); - ESP_LOGD(TAG,"Drawing %d,%d,%d,%d",progress_coordinates->border.x1,progress_coordinates->border.y1,progress_coordinates->border.x2,progress_coordinates->border.y2); - GDS_DrawBox(display,progress_coordinates->border.x1,progress_coordinates->border.y1,progress_coordinates->border.x2,progress_coordinates->border.y2,GDS_COLOR_WHITE,false); - ESP_LOGD(TAG,"Drawing %d,%d,%d,%d",progress_coordinates->filler.x1,progress_coordinates->filler.y1,filler_x,progress_coordinates->filler.y2); - if(filler_x > progress_coordinates->filler.x1){ - GDS_DrawBox(display,progress_coordinates->filler.x1,progress_coordinates->filler.y1,filler_x,progress_coordinates->filler.y2,GDS_COLOR_WHITE,true); - } - else { - // Clear the inner box - GDS_DrawBox(display,progress_coordinates->filler.x1,progress_coordinates->filler.y1,progress_coordinates->filler.x2,progress_coordinates->filler.y2,GDS_COLOR_BLACK,true); - } - ESP_LOGD(TAG,"Updating Display"); - GDS_Update(display); - } - if (led_display) { - led_vu_progress_bar(pct, LED_VU_BRIGHT); - } + ESP_LOGD(TAG, "Drawing %d,%d,%d,%d", progress_coordinates->border.x1, progress_coordinates->border.y1, progress_coordinates->border.x2, + progress_coordinates->border.y2); + GDS_DrawBox(display, progress_coordinates->border.x1, progress_coordinates->border.y1, progress_coordinates->border.x2, + progress_coordinates->border.y2, GDS_COLOR_WHITE, false); + ESP_LOGD( + TAG, "Drawing %d,%d,%d,%d", progress_coordinates->filler.x1, progress_coordinates->filler.y1, filler_x, progress_coordinates->filler.y2); + if(filler_x > progress_coordinates->filler.x1) { + GDS_DrawBox(display, progress_coordinates->filler.x1, progress_coordinates->filler.y1, filler_x, progress_coordinates->filler.y2, + GDS_COLOR_WHITE, true); + } else { + // Clear the inner box + GDS_DrawBox(display, progress_coordinates->filler.x1, progress_coordinates->filler.y1, progress_coordinates->filler.x2, + progress_coordinates->filler.y2, GDS_COLOR_BLACK, true); + } + ESP_LOGD(TAG, "Updating Display"); + GDS_Update(display); + } + if(led_display) { led_vu_progress_bar(pct, LED_VU_BRIGHT); } } -void sendMessaging(messaging_types type,const char * fmt, ...){ +void sendMessaging(messaging_types type, const char* fmt, ...) { va_list args; - cJSON * msg = cJSON_CreateObject(); - size_t str_len=0; - char * msg_str=NULL; + cJSON* msg = cJSON_CreateObject(); + size_t str_len = 0; + char* msg_str = NULL; va_start(args, fmt); - str_len = vsnprintf(NULL,0,fmt,args)+1; - if(str_len>0){ - msg_str = malloc_init_external(str_len); - vsnprintf(msg_str,str_len,fmt,args); - if(type == MESSAGING_WARNING){ - ESP_LOGW(TAG,"%s",msg_str); - } - else if (type == MESSAGING_ERROR){ - ESP_LOGE(TAG,"%s",msg_str); - } - else - ESP_LOGI(TAG,"%s",msg_str); - } - else { - ESP_LOGW(TAG, "Sending empty string message"); + str_len = vsnprintf(NULL, 0, fmt, args) + 1; + if(str_len > 0) { + msg_str = malloc_init_external(str_len); + vsnprintf(msg_str, str_len, fmt, args); + if(type == MESSAGING_WARNING) { + ESP_LOGW(TAG, "%s", msg_str); + } else if(type == MESSAGING_ERROR) { + ESP_LOGE(TAG, "%s", msg_str); + } else + ESP_LOGI(TAG, "%s", msg_str); + } else { + ESP_LOGW(TAG, "Sending empty string message"); } va_end(args); - if(type!=MESSAGING_INFO){ - IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg_str)); - } + if(type != MESSAGING_INFO) { IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg_str)); } - cJSON_AddStringToObject(msg,"ota_dsc",str_or_unknown(msg_str)); + cJSON_AddStringToObject(msg, "ota_dsc", str_or_unknown(msg_str)); free(msg_str); - cJSON_AddNumberToObject(msg,"ota_pct", ota_get_pct_complete() ); - char * json_msg = cJSON_PrintUnformatted(msg); - messaging_post_message(type, MESSAGING_CLASS_OTA, json_msg); - free(json_msg); - cJSON_Delete(msg); + cJSON_AddNumberToObject(msg, "ota_pct", ota_get_pct_complete()); + char* json_msg = cJSON_PrintUnformatted(msg); + messaging_post_message(type, MESSAGING_CLASS_OTA, json_msg); + free(json_msg); + cJSON_Delete(msg); _printMemStats(); } -static void __attribute__((noreturn)) task_fatal_error(void) -{ +static void __attribute__((noreturn)) task_fatal_error(void) { ESP_LOGE(TAG, "Exiting task due to fatal error..."); (void)vTaskDelete(NULL); - while (1) { - ; + while(1) { ; } +} + +esp_err_t handle_http_on_data(esp_http_client_event_t* evt) { + + int http_status = esp_http_client_get_status_code(evt->client); + static char* recv_ptr = NULL; + + if(http_status == 200) { + + if(!ota_status->bOTAStarted) { + sendMessaging(MESSAGING_INFO, "Downloading firmware"); + ota_status->bOTAStarted = true; + ota_status->total_image_len = esp_http_client_get_content_length(evt->client); + ota_status->downloaded_image_len = 0; + ota_status->newdownloadpct = 0; + ota_status->bin_data = malloc_init_external(ota_status->total_image_len); + if(ota_status->bin_data == NULL) { + sendMessaging(MESSAGING_ERROR, "Error: buffer alloc error"); + return ESP_FAIL; + } + recv_ptr = ota_status->bin_data; + } + + // we're downloading the binary data file + if(!esp_http_client_is_chunked_response(evt->client)) { + memcpy(recv_ptr, evt->data, evt->data_len); + ota_status->downloaded_image_len += evt->data_len; + recv_ptr += evt->data_len; + } + if(ota_get_pct_downloaded() % 5 == 0 && ota_get_pct_downloaded() % 5 != ota_status->newdownloadpct) { + ota_status->newdownloadpct = ota_get_pct_downloaded(); + loc_displayer_progressbar(ota_status->newdownloadpct); + gettimeofday(&tv, NULL); + uint32_t elapsed_ms = (tv.tv_sec - ota_status->OTA_start.tv_sec) * 1000 + (tv.tv_usec - ota_status->OTA_start.tv_usec) / 1000; + ESP_LOGI(TAG, "OTA download progress : %f/%f (%d pct), %f KB/s", ota_status->downloaded_image_len, ota_status->total_image_len, + ota_status->newdownloadpct, elapsed_ms > 0 ? ota_status->downloaded_image_len * 1000 / elapsed_ms / 1024 : 0); + sendMessaging(MESSAGING_INFO, "Downloading firmware %%%3d.", ota_status->newdownloadpct); + } } + + return ESP_OK; } +esp_err_t _http_event_handler(esp_http_client_event_t* evt) { + // -------------- + // Received parameters + // + // esp_http_client_event_id_tevent_id event_id, to know the cause of the event + // esp_http_client_handle_t client + // esp_http_client_handle_t context -esp_err_t handle_http_on_data(esp_http_client_event_t *evt){ + // void *data data of the event - int http_status= esp_http_client_get_status_code(evt->client); - static char * recv_ptr=NULL; + // int data_len - data length of data + // void *user_data -- user_data context, from esp_http_client_config_t user_data - if(http_status == 200){ - - - if(!ota_status->bOTAStarted) - { - sendMessaging(MESSAGING_INFO,"Downloading firmware"); - ota_status->bOTAStarted = true; - ota_status->total_image_len=esp_http_client_get_content_length(evt->client); - ota_status->downloaded_image_len = 0; - ota_status->newdownloadpct = 0; - ota_status->bin_data= malloc_init_external(ota_status->total_image_len); - if(ota_status->bin_data==NULL){ - sendMessaging(MESSAGING_ERROR,"Error: buffer alloc error"); - return ESP_FAIL; - } - recv_ptr=ota_status->bin_data; - } - - // we're downloading the binary data file - if (!esp_http_client_is_chunked_response(evt->client)) { - memcpy(recv_ptr,evt->data,evt->data_len); - ota_status->downloaded_image_len +=evt->data_len; - recv_ptr+=evt->data_len; - } - if(ota_get_pct_downloaded()%5 == 0 && ota_get_pct_downloaded()%5!=ota_status->newdownloadpct) { - ota_status->newdownloadpct= ota_get_pct_downloaded(); - loc_displayer_progressbar(ota_status->newdownloadpct); - gettimeofday(&tv, NULL); - uint32_t elapsed_ms= (tv.tv_sec-ota_status->OTA_start.tv_sec )*1000+(tv.tv_usec-ota_status->OTA_start.tv_usec)/1000; - ESP_LOGI(TAG,"OTA download progress : %f/%f (%d pct), %f KB/s", ota_status->downloaded_image_len, ota_status->total_image_len, ota_status->newdownloadpct, elapsed_ms>0?ota_status->downloaded_image_len*1000/elapsed_ms/1024:0); - sendMessaging(MESSAGING_INFO,"Downloading firmware %%%3d.",ota_status->newdownloadpct); - } - - } - - return ESP_OK; -} -esp_err_t _http_event_handler(esp_http_client_event_t *evt) -{ -// -------------- -// Received parameters -// -// esp_http_client_event_id_tevent_id event_id, to know the cause of the event -// esp_http_client_handle_t client -// esp_http_client_handle_t context - -// void *data data of the event - -// int data_len - data length of data -// void *user_data -- user_data context, from esp_http_client_config_t user_data - -// char *header_key For HTTP_EVENT_ON_HEADER event_id, it�s store current http header key -// char *header_value For HTTP_EVENT_ON_HEADER event_id, it�s store current http header value -// -------------- - switch (evt->event_id) { + // char *header_key For HTTP_EVENT_ON_HEADER event_id, it�s store current http header key + // char *header_value For HTTP_EVENT_ON_HEADER event_id, it�s store current http header value + // -------------- + switch(evt->event_id) { case HTTP_EVENT_ERROR: ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); _printMemStats(); break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - if(ota_status->bOTAStarted) sendMessaging(MESSAGING_INFO,"HTTP Connected"); - ota_status->total_image_len=0; - ota_status->actual_image_len=0; - ota_status->lastpct=0; - ota_status->remain_image_len=0; - ota_status->newpct=0; - gettimeofday(&ota_status->OTA_start, NULL); - break; + if(ota_status->bOTAStarted) sendMessaging(MESSAGING_INFO, "HTTP Connected"); + ota_status->total_image_len = 0; + ota_status->actual_image_len = 0; + ota_status->lastpct = 0; + ota_status->remain_image_len = 0; + ota_status->newpct = 0; + gettimeofday(&ota_status->OTA_start, NULL); + break; case HTTP_EVENT_HEADER_SENT: ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); break; case HTTP_EVENT_ON_HEADER: - ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s",evt->header_key, evt->header_value); -// if (strcasecmp(evt->header_key, "location") == 0) { -// ESP_LOGW(TAG,"OTA will redirect to url: %s",evt->header_value); -// } -// if (strcasecmp(evt->header_key, "content-length") == 0) { -// ota_status->total_image_len = atol(evt->header_value); -// ESP_LOGW(TAG, "Content length found: %s, parsed to %d", evt->header_value, ota_status->total_image_len); -// } + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + // if (strcasecmp(evt->header_key, "location") == 0) { + // ESP_LOGW(TAG,"OTA will redirect to url: %s",evt->header_value); + // } + // if (strcasecmp(evt->header_key, "content-length") == 0) { + // ota_status->total_image_len = atol(evt->header_value); + // ESP_LOGW(TAG, "Content length found: %s, parsed to %d", evt->header_value, ota_status->total_image_len); + // } break; case HTTP_EVENT_ON_DATA: - return handle_http_on_data(evt); + return handle_http_on_data(evt); break; case HTTP_EVENT_ON_FINISH: ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); @@ -330,382 +310,375 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) return ESP_OK; } -esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){ - memset(&http_client_config, 0x00, sizeof(http_client_config)); - sendMessaging(MESSAGING_INFO,"Initializing..."); - loc_displayer_progressbar(0); - ota_status->ota_type= OTA_TYPE_INVALID; - if(p_ota_thread_parms->url !=NULL && strlen(p_ota_thread_parms->url)>0 ){ - ota_status->ota_type= OTA_TYPE_HTTP; - } - else if(p_ota_thread_parms->bin!=NULL && p_ota_thread_parms->length > 0) { - ota_status->ota_type= OTA_TYPE_BUFFER; - } +esp_err_t init_config(ota_thread_parms_t* p_ota_thread_parms) { + memset(&http_client_config, 0x00, sizeof(http_client_config)); + sendMessaging(MESSAGING_INFO, "Initializing..."); + loc_displayer_progressbar(0); + ota_status->ota_type = OTA_TYPE_INVALID; + if(p_ota_thread_parms->url != NULL && strlen(p_ota_thread_parms->url) > 0) { + ota_status->ota_type = OTA_TYPE_HTTP; + } else if(p_ota_thread_parms->bin != NULL && p_ota_thread_parms->length > 0) { + ota_status->ota_type = OTA_TYPE_BUFFER; + } - if( ota_status->ota_type== OTA_TYPE_INVALID ){ - ESP_LOGE(TAG,"HTTP OTA called without a url or a binary buffer"); - return ESP_ERR_INVALID_ARG; - } + if(ota_status->ota_type == OTA_TYPE_INVALID) { + ESP_LOGE(TAG, "HTTP OTA called without a url or a binary buffer"); + return ESP_ERR_INVALID_ARG; + } - ota_status->buffer_size = BUFFSIZE; - ota_status->ota_write_data = heap_caps_malloc(ota_status->buffer_size+1 , (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)); - if(ota_status->ota_write_data== NULL){ - ESP_LOGE(TAG,"Error allocating the ota buffer"); - return ESP_ERR_NO_MEM; - } - switch (ota_status->ota_type) { - case OTA_TYPE_HTTP: - http_client_config.event_handler = _http_event_handler; - http_client_config.disable_auto_redirect=false; - http_client_config.skip_cert_common_name_check = false; - http_client_config.url = strdup_psram(p_ota_thread_parms->url); - http_client_config.max_redirection_count = 4; - // buffer size below is for http read chunks - http_client_config.buffer_size = 8192; //1024 ; - http_client_config.buffer_size_tx = 8192; - //http_client_config.timeout_ms = 5000; - break; - case OTA_TYPE_BUFFER: - ota_status->bin_data = p_ota_thread_parms->bin; - ota_status->total_image_len = p_ota_thread_parms->length; - break; - default: - return ESP_FAIL; - break; - } + ota_status->buffer_size = BUFFSIZE; + ota_status->ota_write_data = heap_caps_malloc(ota_status->buffer_size + 1, (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)); + if(ota_status->ota_write_data == NULL) { + ESP_LOGE(TAG, "Error allocating the ota buffer"); + return ESP_ERR_NO_MEM; + } + switch(ota_status->ota_type) { + case OTA_TYPE_HTTP: + http_client_config.event_handler = _http_event_handler; + http_client_config.disable_auto_redirect = false; + http_client_config.skip_cert_common_name_check = false; + http_client_config.url = strdup_psram(p_ota_thread_parms->url); + http_client_config.max_redirection_count = 4; + // buffer size below is for http read chunks + http_client_config.buffer_size = 8192; //1024 ; + http_client_config.buffer_size_tx = 8192; + //http_client_config.timeout_ms = 5000; + break; + case OTA_TYPE_BUFFER: + ota_status->bin_data = p_ota_thread_parms->bin; + ota_status->total_image_len = p_ota_thread_parms->length; + break; + default: + return ESP_FAIL; + break; + } - return ESP_OK; + return ESP_OK; } -esp_partition_t * _get_ota_partition(esp_partition_subtype_t subtype){ - esp_partition_t *ota_partition=NULL; - ESP_LOGD(TAG, "Looking for OTA partition."); - - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, subtype , NULL); - if(it == NULL){ - ESP_LOGE(TAG,"Unable initialize partition iterator!"); - } - else { - ota_partition = (esp_partition_t *) esp_partition_get(it); - if(ota_partition != NULL){ - ESP_LOGD(TAG, "Found OTA partition: %s.",ota_partition->label); - } - else { - ESP_LOGE(TAG,"OTA partition not found! Unable update application."); - } - esp_partition_iterator_release(it); - } - return ota_partition; +esp_partition_t* _get_ota_partition(esp_partition_subtype_t subtype) { + esp_partition_t* ota_partition = NULL; + ESP_LOGD(TAG, "Looking for OTA partition."); + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, subtype, NULL); + if(it == NULL) { + ESP_LOGE(TAG, "Unable initialize partition iterator!"); + } else { + ota_partition = (esp_partition_t*)esp_partition_get(it); + if(ota_partition != NULL) { + ESP_LOGD(TAG, "Found OTA partition: %s.", ota_partition->label); + } else { + ESP_LOGE(TAG, "OTA partition not found! Unable update application."); + } + esp_partition_iterator_release(it); + } + return ota_partition; } +esp_err_t _erase_last_boot_app_partition(const esp_partition_t* ota_partition) { + uint16_t num_passes = 0; + uint16_t remain_size = 0; + uint32_t single_pass_size = OTA_FLASH_ERASE_BLOCK; + esp_err_t err = ESP_OK; + if(single_pass_size % SPI_FLASH_SEC_SIZE != 0) { + uint32_t temp_single_pass_size = single_pass_size - (single_pass_size % SPI_FLASH_SEC_SIZE); + ESP_LOGW(TAG, "Invalid erase block size of %u. Value should be a multiple of %d and will be adjusted to %u.", single_pass_size, + SPI_FLASH_SEC_SIZE, temp_single_pass_size); + single_pass_size = temp_single_pass_size; + } + ESP_LOGD(TAG, "Erasing flash partition of size %u in blocks of %d bytes", ota_partition->size, single_pass_size); + num_passes = ota_partition->size / single_pass_size; + remain_size = ota_partition->size - (num_passes * single_pass_size); + ESP_LOGI(TAG, "Erasing in %d passes with blocks of %d bytes ", num_passes, single_pass_size); + for(uint16_t i = 0; i < num_passes; i++) { + ESP_LOGD(TAG, "Erasing flash (%u%%)", i / num_passes); + ESP_LOGD(TAG, "Pass %d of %d, with chunks of %d bytes, from %d to %d", i + 1, num_passes, single_pass_size, i * single_pass_size, + i * single_pass_size + single_pass_size); + err = esp_partition_erase_range(ota_partition, i * single_pass_size, single_pass_size); + if(err != ESP_OK) return err; + if(i % 2) { + loc_displayer_progressbar((int)(((float)i / (float)num_passes) * 100.0f)); + sendMessaging(MESSAGING_INFO, "Erasing flash (%u/%u)", i, num_passes); + } + vTaskDelay(100 / portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors + } + if(remain_size > 0) { + err = esp_partition_erase_range(ota_partition, ota_partition->size - remain_size, remain_size); -esp_err_t _erase_last_boot_app_partition(const esp_partition_t *ota_partition) -{ - uint16_t num_passes=0; - uint16_t remain_size=0; - uint32_t single_pass_size=OTA_FLASH_ERASE_BLOCK; - esp_err_t err=ESP_OK; - - - if(single_pass_size % SPI_FLASH_SEC_SIZE !=0){ - uint32_t temp_single_pass_size = single_pass_size-(single_pass_size % SPI_FLASH_SEC_SIZE); - ESP_LOGW(TAG,"Invalid erase block size of %u. Value should be a multiple of %d and will be adjusted to %u.", single_pass_size, SPI_FLASH_SEC_SIZE,temp_single_pass_size); - single_pass_size=temp_single_pass_size; - } - ESP_LOGD(TAG,"Erasing flash partition of size %u in blocks of %d bytes", ota_partition->size, single_pass_size); - num_passes=ota_partition->size/single_pass_size; - remain_size=ota_partition->size-(num_passes*single_pass_size); - ESP_LOGI(TAG,"Erasing in %d passes with blocks of %d bytes ", num_passes,single_pass_size); - for(uint16_t i=0;i0){ - err=esp_partition_erase_range(ota_partition, ota_partition->size-remain_size, remain_size); - - if(err!=ESP_OK) return err; - } - sendMessaging(MESSAGING_INFO,"Erasing flash complete."); - loc_displayer_progressbar(100); - vTaskDelay(200/ portTICK_PERIOD_MS); - // TODO: Add support for the commented code - return ESP_OK; + if(err != ESP_OK) return err; + } + sendMessaging(MESSAGING_INFO, "Erasing flash complete."); + loc_displayer_progressbar(100); + vTaskDelay(200 / portTICK_PERIOD_MS); + // TODO: Add support for the commented code + return ESP_OK; } -void ota_task_cleanup(const char * message, ...){ - // TODO: Add support for the commented code - // ota_status->bOTAThreadStarted=false; - // loc_displayer_progressbar(0); - // if(message!=NULL){ - // va_list args; - // va_start(args, message); - // sendMessaging(MESSAGING_ERROR,message, args); - // va_end(args); - - // if (led_display) led_vu_color_red(LED_VU_BRIGHT); - // } else { - // if (led_display) led_vu_color_green(LED_VU_BRIGHT); - // } - // FREE_RESET(ota_status->ota_write_data); - // FREE_RESET(ota_status->bin_data); - // if(ota_http_client!=NULL) { - // esp_http_client_cleanup(ota_http_client); - // ota_http_client=NULL; - // } - // ota_status->bOTAStarted = false; - // task_fatal_error(); -} -esp_err_t ota_buffer_all(){ - esp_err_t err=ESP_OK; - if (ota_status->ota_type == OTA_TYPE_HTTP){ - IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Downloading file")); - ota_http_client = esp_http_client_init(&http_client_config); - if (ota_http_client == NULL) { - sendMessaging(MESSAGING_ERROR,"Error: Failed to initialize HTTP connection."); - return ESP_FAIL; - } - _printMemStats(); - err = esp_http_client_perform(ota_http_client); - if (err != ESP_OK) { - sendMessaging(MESSAGING_ERROR,"Error: Failed to execute HTTP download. %s",esp_err_to_name(err)); - return ESP_FAIL; - } +void ota_task_cleanup(const char* message, ...) { + // TODO: Add support for the commented code + // ota_status->bOTAThreadStarted=false; + // loc_displayer_progressbar(0); + // if(message!=NULL){ + // va_list args; + // va_start(args, message); + // sendMessaging(MESSAGING_ERROR,message, args); + // va_end(args); - if(ota_status->total_image_len<=0){ - sendMessaging(MESSAGING_ERROR,"Error: Invalid image length"); - return ESP_FAIL; - } - sendMessaging(MESSAGING_INFO,"Download success"); - } - else { - gettimeofday(&ota_status->OTA_start, NULL); - } - ota_status->remain_image_len=ota_status->total_image_len; - - return err; + // if (led_display) led_vu_color_red(LED_VU_BRIGHT); + // } else { + // if (led_display) led_vu_color_green(LED_VU_BRIGHT); + // } + // FREE_RESET(ota_status->ota_write_data); + // FREE_RESET(ota_status->bin_data); + // if(ota_http_client!=NULL) { + // esp_http_client_cleanup(ota_http_client); + // ota_http_client=NULL; + // } + // ota_status->bOTAStarted = false; + // task_fatal_error(); } -int ota_buffer_read(){ - int data_read=0; - if(ota_status->remain_image_len >ota_status->buffer_size){ - data_read = ota_status->buffer_size; - } else { - data_read = ota_status->remain_image_len; - } - memcpy(ota_status->ota_write_data, &ota_status->bin_data[ota_status->actual_image_len], data_read); +esp_err_t ota_buffer_all() { + esp_err_t err = ESP_OK; + if(ota_status->ota_type == OTA_TYPE_HTTP) { + IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Downloading file")); + ota_http_client = esp_http_client_init(&http_client_config); + if(ota_http_client == NULL) { + sendMessaging(MESSAGING_ERROR, "Error: Failed to initialize HTTP connection."); + return ESP_FAIL; + } + _printMemStats(); + err = esp_http_client_perform(ota_http_client); + if(err != ESP_OK) { + sendMessaging(MESSAGING_ERROR, "Error: Failed to execute HTTP download. %s", esp_err_to_name(err)); + return ESP_FAIL; + } - ota_status->actual_image_len += data_read; - ota_status->remain_image_len -= data_read; - return data_read; + if(ota_status->total_image_len <= 0) { + sendMessaging(MESSAGING_ERROR, "Error: Invalid image length"); + return ESP_FAIL; + } + sendMessaging(MESSAGING_INFO, "Download success"); + } else { + gettimeofday(&ota_status->OTA_start, NULL); + } + ota_status->remain_image_len = ota_status->total_image_len; + + return err; } -esp_err_t ota_header_check(){ - esp_app_desc_t new_app_info; +int ota_buffer_read() { + int data_read = 0; + if(ota_status->remain_image_len > ota_status->buffer_size) { + data_read = ota_status->buffer_size; + } else { + data_read = ota_status->remain_image_len; + } + memcpy(ota_status->ota_write_data, &ota_status->bin_data[ota_status->actual_image_len], data_read); + + ota_status->actual_image_len += data_read; + ota_status->remain_image_len -= data_read; + return data_read; +} +esp_err_t ota_header_check() { + esp_app_desc_t new_app_info; esp_app_desc_t running_app_info; ota_status->configured = esp_ota_get_boot_partition(); ota_status->running = esp_ota_get_running_partition(); - ota_status->last_invalid_app= esp_ota_get_last_invalid_partition(); + ota_status->last_invalid_app = esp_ota_get_last_invalid_partition(); ota_status->ota_partition = _get_ota_partition(ESP_PARTITION_SUBTYPE_APP_OTA_0); - ESP_LOGD(TAG, "Running partition [%s] type %d subtype %d (offset 0x%08x)", ota_status->running->label, ota_status->running->type, ota_status->running->subtype, ota_status->running->address); - if (ota_status->total_image_len > ota_status->ota_partition->size){ - ota_task_cleanup("Error: Image size (%d) too large to fit in partition (%d).",ota_status->ota_partition->size,ota_status->total_image_len ); + ESP_LOGD(TAG, "Running partition [%s] type %d subtype %d (offset 0x%08x)", ota_status->running->label, ota_status->running->type, + ota_status->running->subtype, ota_status->running->address); + if(ota_status->total_image_len > ota_status->ota_partition->size) { + ota_task_cleanup("Error: Image size (%d) too large to fit in partition (%d).", ota_status->ota_partition->size, ota_status->total_image_len); return ESP_FAIL; - } - if(ota_status->ota_partition == NULL){ - ESP_LOGE(TAG,"Unable to locate OTA application partition. "); + } + if(ota_status->ota_partition == NULL) { + ESP_LOGE(TAG, "Unable to locate OTA application partition. "); ota_task_cleanup("Error: OTA partition not found"); return ESP_FAIL; - } - if (ota_status->configured != ota_status->running) { - ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", ota_status->configured->address, ota_status->running->address); + } + if(ota_status->configured != ota_status->running) { + ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", ota_status->configured->address, + ota_status->running->address); ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); } - ESP_LOGD(TAG, "Next ota update partition is: [%s] subtype %d at offset 0x%x", - ota_status->update_partition->label, ota_status->update_partition->subtype, ota_status->update_partition->address); + ESP_LOGD(TAG, "Next ota update partition is: [%s] subtype %d at offset 0x%x", ota_status->update_partition->label, + ota_status->update_partition->subtype, ota_status->update_partition->address); - if (ota_status->total_image_len >= IMAGE_HEADER_SIZE) { - // check current version with downloading - memcpy(&new_app_info, &ota_status->bin_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); - ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); - if (esp_ota_get_partition_description(ota_status->running, &running_app_info) == ESP_OK) { - ESP_LOGD(TAG, "Running recovery version: %s", running_app_info.version); - } - sendMessaging(MESSAGING_INFO,"New version is : %s",new_app_info.version); - esp_app_desc_t invalid_app_info; - if (esp_ota_get_partition_description(ota_status->last_invalid_app, &invalid_app_info) == ESP_OK) { - ESP_LOGD(TAG, "Last invalid firmware version: %s", invalid_app_info.version); - } + if(ota_status->total_image_len >= IMAGE_HEADER_SIZE) { + // check current version with downloading + memcpy(&new_app_info, &ota_status->bin_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); + ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); + if(esp_ota_get_partition_description(ota_status->running, &running_app_info) == ESP_OK) { + ESP_LOGD(TAG, "Running recovery version: %s", running_app_info.version); + } + sendMessaging(MESSAGING_INFO, "New version is : %s", new_app_info.version); + esp_app_desc_t invalid_app_info; + if(esp_ota_get_partition_description(ota_status->last_invalid_app, &invalid_app_info) == ESP_OK) { + ESP_LOGD(TAG, "Last invalid firmware version: %s", invalid_app_info.version); + } - if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { - ESP_LOGW(TAG, "Current running version is the same as a new."); - } - return ESP_OK; + if(memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { + ESP_LOGW(TAG, "Current running version is the same as a new."); + } + return ESP_OK; + } else { + ota_task_cleanup("Error: Binary file too small"); } - else{ - ota_task_cleanup("Error: Binary file too small"); - } - return ESP_FAIL; + return ESP_FAIL; } -void ota_task(void *pvParameter) -{ - esp_err_t err = ESP_OK; +void ota_task(void* pvParameter) { + esp_err_t err = ESP_OK; int data_read = 0; - IF_DISPLAY(GDS_TextSetFontAuto(display,2,GDS_GetHeight(display)>32?GDS_FONT_LARGE:GDS_FONT_MEDIUM,-2)) - IF_DISPLAY( GDS_ClearExt(display, true)); - IF_DISPLAY(GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Firmware update")); - IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Initializing")); - loc_displayer_progressbar(0); - ESP_LOGD(TAG, "HTTP ota Thread started"); + IF_DISPLAY(GDS_TextSetFontAuto(display, 2, GDS_GetHeight(display) > 32 ? GDS_FONT_LARGE : GDS_FONT_MEDIUM, -2)) + IF_DISPLAY(GDS_ClearExt(display, true)); + IF_DISPLAY(GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Firmware update")); + IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Initializing")); + loc_displayer_progressbar(0); + ESP_LOGD(TAG, "HTTP ota Thread started"); _printMemStats(); ota_status->update_partition = esp_ota_get_next_update_partition(NULL); - ESP_LOGD(TAG,"Initializing OTA configuration"); - err = init_config(pvParameter); - if(err!=ESP_OK){ - ota_task_cleanup("Error: Failed to initialize OTA."); - return; - } + ESP_LOGD(TAG, "Initializing OTA configuration"); + err = init_config(pvParameter); + if(err != ESP_OK) { + ota_task_cleanup("Error: Failed to initialize OTA."); + return; + } - _printMemStats(); - sendMessaging(MESSAGING_INFO,"Starting OTA..."); - err=ota_buffer_all(); - if(err!=ESP_OK){ - ota_task_cleanup(NULL); - return; - } + _printMemStats(); + sendMessaging(MESSAGING_INFO, "Starting OTA..."); + err = ota_buffer_all(); + if(err != ESP_OK) { + ota_task_cleanup(NULL); + return; + } - if(ota_header_check()!=ESP_OK){ - ota_task_cleanup(NULL); - return; - } + if(ota_header_check() != ESP_OK) { + ota_task_cleanup(NULL); + return; + } - /* Locate and erase ota application partition */ - sendMessaging(MESSAGING_INFO,"Formatting OTA partition"); - ESP_LOGW(TAG,"**************** Expecting WATCHDOG errors below during flash erase. This is OK and not to worry about **************** "); - IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Formatting partition")); + /* Locate and erase ota application partition */ + sendMessaging(MESSAGING_INFO, "Formatting OTA partition"); + ESP_LOGW(TAG, "**************** Expecting WATCHDOG errors below during flash erase. This is OK and not to worry about **************** "); + IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Formatting partition")); - _printMemStats(); - err=_erase_last_boot_app_partition(ota_status->ota_partition); - if(err!=ESP_OK){ - ota_task_cleanup("Error: Unable to erase last APP partition. (%s)",esp_err_to_name(err)); - return; - } - loc_displayer_progressbar(0); - _printMemStats(); + _printMemStats(); + err = _erase_last_boot_app_partition(ota_status->ota_partition); + if(err != ESP_OK) { + ota_task_cleanup("Error: Unable to erase last APP partition. (%s)", esp_err_to_name(err)); + return; + } + loc_displayer_progressbar(0); + _printMemStats(); - - // Call OTA Begin with a small partition size - this minimizes the time spent in erasing partition, - // which was already done above - esp_ota_handle_t update_handle = 0 ; + // Call OTA Begin with a small partition size - this minimizes the time spent in erasing partition, + // which was already done above + esp_ota_handle_t update_handle = 0; gettimeofday(&ota_status->OTA_start, NULL); - err = esp_ota_begin(ota_status->ota_partition, 512, &update_handle); - if (err != ESP_OK) { - ota_task_cleanup("esp_ota_begin failed (%s)", esp_err_to_name(err)); - return; - } - ESP_LOGD(TAG, "esp_ota_begin succeeded"); - IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Writing image...")); - while (ota_status->remain_image_len>0) { + err = esp_ota_begin(ota_status->ota_partition, 512, &update_handle); + if(err != ESP_OK) { + ota_task_cleanup("esp_ota_begin failed (%s)", esp_err_to_name(err)); + return; + } + ESP_LOGD(TAG, "esp_ota_begin succeeded"); + IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Writing image...")); + while(ota_status->remain_image_len > 0) { - data_read = ota_buffer_read(); - if (data_read <= 0) { + data_read = ota_buffer_read(); + if(data_read <= 0) { ota_task_cleanup("Error: Data read error"); return; - } else if (data_read > 0) { - err = esp_ota_write( update_handle, (const void *)ota_status->ota_write_data, data_read); - if (err != ESP_OK) { - ota_task_cleanup("Error: OTA Partition write failure. (%s)",esp_err_to_name(err)); + } else if(data_read > 0) { + err = esp_ota_write(update_handle, (const void*)ota_status->ota_write_data, data_read); + if(err != ESP_OK) { + ota_task_cleanup("Error: OTA Partition write failure. (%s)", esp_err_to_name(err)); return; } ESP_LOGD(TAG, "Written image length %d", ota_status->actual_image_len); - if(ota_get_pct_complete()%5 == 0) ota_status->newpct = ota_get_pct_complete(); - if(ota_status->lastpct!=ota_status->newpct ) { - loc_displayer_progressbar(ota_status->newpct); - gettimeofday(&tv, NULL); - uint32_t elapsed_ms= (tv.tv_sec-ota_status->OTA_start.tv_sec )*1000+(tv.tv_usec-ota_status->OTA_start.tv_usec)/1000; - ESP_LOGI(TAG,"OTA progress : %d/%.0f (%d pct), %d KB/s", ota_status->actual_image_len, ota_status->total_image_len, ota_status->newpct, elapsed_ms>0?ota_status->actual_image_len*1000/elapsed_ms/1024:0); - sendMessaging(MESSAGING_INFO,"Writing binary file %3d %%.",ota_status->newpct); - ota_status->lastpct=ota_status->newpct; - } - taskYIELD(); + if(ota_get_pct_complete() % 5 == 0) ota_status->newpct = ota_get_pct_complete(); + if(ota_status->lastpct != ota_status->newpct) { + loc_displayer_progressbar(ota_status->newpct); + gettimeofday(&tv, NULL); + uint32_t elapsed_ms = (tv.tv_sec - ota_status->OTA_start.tv_sec) * 1000 + (tv.tv_usec - ota_status->OTA_start.tv_usec) / 1000; + ESP_LOGI(TAG, "OTA progress : %d/%.0f (%d pct), %d KB/s", ota_status->actual_image_len, ota_status->total_image_len, + ota_status->newpct, elapsed_ms > 0 ? ota_status->actual_image_len * 1000 / elapsed_ms / 1024 : 0); + sendMessaging(MESSAGING_INFO, "Writing binary file %3d %%.", ota_status->newpct); + ota_status->lastpct = ota_status->newpct; + } + taskYIELD(); - } else if (data_read == 0) { + } else if(data_read == 0) { ESP_LOGD(TAG, "End of OTA data stream"); break; } } ESP_LOGI(TAG, "Total Write binary data length: %d", ota_status->actual_image_len); - if (ota_status->total_image_len != ota_status->actual_image_len) { + if(ota_status->total_image_len != ota_status->actual_image_len) { ota_task_cleanup("Error: Error in receiving complete file"); return; } _printMemStats(); loc_displayer_progressbar(100); err = esp_ota_end(update_handle); - if (err != ESP_OK) { - ota_task_cleanup("Error: %s",esp_err_to_name(err)); + if(err != ESP_OK) { + ota_task_cleanup("Error: %s", esp_err_to_name(err)); return; - } + } _printMemStats(); err = esp_ota_set_boot_partition(ota_status->ota_partition); - if (err == ESP_OK) { - ESP_LOGI(TAG,"OTA Process completed successfully!"); - sendMessaging(MESSAGING_INFO,"Success!"); - IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Success!")); - vTaskDelay(3500/ portTICK_PERIOD_MS); // wait here to give the UI a chance to refresh - IF_DISPLAY(GDS_Clear(display,GDS_COLOR_BLACK)); + if(err == ESP_OK) { + ESP_LOGI(TAG, "OTA Process completed successfully!"); + sendMessaging(MESSAGING_INFO, "Success!"); + IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Success!")); + vTaskDelay(3500 / portTICK_PERIOD_MS); // wait here to give the UI a chance to refresh + IF_DISPLAY(GDS_Clear(display, GDS_COLOR_BLACK)); esp_restart(); } else { - ota_task_cleanup("Error: Unable to update boot partition [%s]",esp_err_to_name(err)); + ota_task_cleanup("Error: Unable to update boot partition [%s]", esp_err_to_name(err)); return; } ota_task_cleanup(NULL); return; } -esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length){ - int ret = 0; - uint16_t stack_size, task_priority; +esp_err_t process_recovery_ota(const char* bin_url, char* bin_buffer, uint32_t length) { + int ret = 0; + uint16_t stack_size, task_priority; - if(ota_status && ota_status->bOTAThreadStarted){ - ESP_LOGE(TAG,"OTA Already started. "); - return ESP_FAIL; - } - ota_status = malloc_init_external(sizeof(ota_status_t)); - ota_status->bOTAThreadStarted=true; + if(ota_status && ota_status->bOTAThreadStarted) { + ESP_LOGE(TAG, "OTA Already started. "); + return ESP_FAIL; + } + ota_status = malloc_init_external(sizeof(ota_status_t)); + ota_status->bOTAThreadStarted = true; - if(bin_url){ - ESP_LOGI(TAG,"Processing recovery OTA for url %s",STR_OR_ALT(bin_url,"N/A")); - ota_thread_parms.url =strdup_psram(bin_url); - system_set_string(&sys_state_data_msg,sys_state_data_ota_url_tag,sys_state,NULL); - config_raise_state_changed(); - ESP_LOGD(TAG, "Starting ota on core %u for : %s", OTA_CORE,ota_thread_parms.url); - } - else { - ota_thread_parms.bin = bin_buffer; - ota_thread_parms.length = length; - ESP_LOGD(TAG, "Starting ota on core %u for file upload", OTA_CORE); - } - stack_size = OTA_STACK_SIZE; - task_priority= OTA_TASK_PRIOTITY; + if(bin_url) { + ESP_LOGI(TAG, "Processing recovery OTA for url %s", STR_OR_ALT(bin_url, "N/A")); + ota_thread_parms.url = strdup_psram(bin_url); + system_set_string(&sys_state_data_msg, sys_state_data_ota_url_tag, sys_state, NULL); + config_raise_state_changed(); + ESP_LOGD(TAG, "Starting ota on core %u for : %s", OTA_CORE, ota_thread_parms.url); + } else { + ota_thread_parms.bin = bin_buffer; + ota_thread_parms.length = length; + ESP_LOGD(TAG, "Starting ota on core %u for file upload", OTA_CORE); + } + stack_size = OTA_STACK_SIZE; + task_priority = OTA_TASK_PRIOTITY; - ESP_LOGD(TAG,"OTA task stack size %d, priority %d (%d %s ESP_TASK_MAIN_PRIO)",stack_size , task_priority, abs(task_priority-ESP_TASK_MAIN_PRIO), task_priority-ESP_TASK_MAIN_PRIO>0?"above":"below"); - ret=xTaskCreate(&ota_task, "ota_task", stack_size , (void *)&ota_thread_parms, task_priority, NULL); - if (ret != pdPASS) { - ESP_LOGE(TAG, "create thread %s failed", "ota_task"); - return ESP_FAIL; + ESP_LOGD(TAG, "OTA task stack size %d, priority %d (%d %s ESP_TASK_MAIN_PRIO)", stack_size, task_priority, + abs(task_priority - ESP_TASK_MAIN_PRIO), task_priority - ESP_TASK_MAIN_PRIO > 0 ? "above" : "below"); + ret = xTaskCreate(&ota_task, "ota_task", stack_size, (void*)&ota_thread_parms, task_priority, NULL); + if(ret != pdPASS) { + ESP_LOGE(TAG, "create thread %s failed", "ota_task"); + return ESP_FAIL; } return ESP_OK; } @@ -713,72 +686,70 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t extern void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport); in_addr_t discover_ota_server(int max) { - struct sockaddr_in d; - struct sockaddr_in s; - char buf[32], port_d[] = "JSON", clip_d[] = "CLIP"; - struct pollfd pollinfo; - uint8_t len; - uint16_t hport=9000; - uint16_t cport=9090; + struct sockaddr_in d; + struct sockaddr_in s; + char buf[32], port_d[] = "JSON", clip_d[] = "CLIP"; + struct pollfd pollinfo; + uint8_t len; + uint16_t hport = 9000; + uint16_t cport = 9090; - int disc_sock = socket(AF_INET, SOCK_DGRAM, 0); + int disc_sock = socket(AF_INET, SOCK_DGRAM, 0); - socklen_t enable = 1; - setsockopt(disc_sock, SOL_SOCKET, SO_BROADCAST, (const void *)&enable, sizeof(enable)); + socklen_t enable = 1; + setsockopt(disc_sock, SOL_SOCKET, SO_BROADCAST, (const void*)&enable, sizeof(enable)); - len = sprintf(buf,"e%s%c%s", port_d, '\0', clip_d) + 1; + len = sprintf(buf, "e%s%c%s", port_d, '\0', clip_d) + 1; - memset(&d, 0, sizeof(d)); - d.sin_family = AF_INET; - d.sin_port = htons(3483); - d.sin_addr.s_addr = htonl(INADDR_BROADCAST); + memset(&d, 0, sizeof(d)); + d.sin_family = AF_INET; + d.sin_port = htons(3483); + d.sin_addr.s_addr = htonl(INADDR_BROADCAST); - pollinfo.fd = disc_sock; - pollinfo.events = POLLIN; + pollinfo.fd = disc_sock; + pollinfo.events = POLLIN; - do { + do { - ESP_LOGI(TAG,"sending LMS discovery for OTA Update"); - memset(&s, 0, sizeof(s)); + ESP_LOGI(TAG, "sending LMS discovery for OTA Update"); + memset(&s, 0, sizeof(s)); - if (sendto(disc_sock, buf, len, 0, (struct sockaddr *)&d, sizeof(d)) < 0) { - ESP_LOGE(TAG,"error sending discovery"); - } - else { + if(sendto(disc_sock, buf, len, 0, (struct sockaddr*)&d, sizeof(d)) < 0) { + ESP_LOGE(TAG, "error sending discovery"); + } else { - if (poll(&pollinfo, 1, 5000) == 1) { - char readbuf[64], *p; - socklen_t slen = sizeof(s); - memset(readbuf, 0, sizeof(readbuf)); - recvfrom(disc_sock, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr *)&s, &slen); - ESP_LOGI(TAG,"got response from: %s:%d - %s", inet_ntoa(s.sin_addr), ntohs(s.sin_port),readbuf); + if(poll(&pollinfo, 1, 5000) == 1) { + char readbuf[64], *p; + socklen_t slen = sizeof(s); + memset(readbuf, 0, sizeof(readbuf)); + recvfrom(disc_sock, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr*)&s, &slen); + ESP_LOGI(TAG, "got response from: %s:%d - %s", inet_ntoa(s.sin_addr), ntohs(s.sin_port), readbuf); - if ((p = strstr(readbuf, port_d)) != NULL) { - p += strlen(port_d); - hport = atoi(p + 1); - } + if((p = strstr(readbuf, port_d)) != NULL) { + p += strlen(port_d); + hport = atoi(p + 1); + } - if ((p = strstr(readbuf, clip_d)) != NULL) { - p += strlen(clip_d); - cport = atoi(p + 1); - } - server_notify(s.sin_addr.s_addr, hport, cport); - } - } + if((p = strstr(readbuf, clip_d)) != NULL) { + p += strlen(clip_d); + cport = atoi(p + 1); + } + server_notify(s.sin_addr.s_addr, hport, cport); + } + } - } while (s.sin_addr.s_addr == 0 && (!max || --max)); + } while(s.sin_addr.s_addr == 0 && (!max || --max)); - closesocket(disc_sock); + closesocket(disc_sock); - return s.sin_addr.s_addr; + return s.sin_addr.s_addr; } - // Callback to handle ota when an IP address is obtained void cb_handle_ota(nm_state_t new_state, int sub_state) { - if (sys_state && sys_state->ota_url && strlen(sys_state->ota_url)) { + if(sys_state && sys_state->ota_url && strlen(sys_state->ota_url)) { ESP_LOGD(TAG, "Found OTA URL %s", sys_state->ota_url); - if (is_recovery_running) { + if(is_recovery_running) { ESP_LOGI(TAG, "Updating firmware from link: %s", sys_state->ota_url); #if defined(CONFIG_WITH_METRICS) metrics_event("fw_update"); diff --git a/components/squeezelite-ota/squeezelite-ota.h b/components/squeezelite-ota/squeezelite-ota.h index d26264ef..cb89eb16 100644 --- a/components/squeezelite-ota/squeezelite-ota.h +++ b/components/squeezelite-ota/squeezelite-ota.h @@ -27,11 +27,10 @@ // tasks #define OTA_TASK_PRIOTITY 6 - -const char * ota_get_status(); +const char* ota_get_status(); uint8_t ota_get_pct_complete(); -esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length); +esp_err_t start_ota(const char* bin_url, char* bin_buffer, uint32_t length); in_addr_t discover_ota_server(int max); // Callback to handle ota when an IP address is obtained diff --git a/components/targets/muse/muse.c b/components/targets/muse/muse.c index 71b0a62f..bd925dc4 100644 --- a/components/targets/muse/muse.c +++ b/components/targets/muse/muse.c @@ -15,25 +15,25 @@ ///////////////////////////////////////////////////////////////// //*********************** NeoPixels *************************** //////////////////////////////////////////////////////////////// -#define NUM_LEDS 1 -#define LED_RMT_TX_GPIO 22 +#define NUM_LEDS 1 +#define LED_RMT_TX_GPIO 22 -#define BITS_PER_LED_CMD 24 +#define BITS_PER_LED_CMD 24 #define LED_BUFFER_ITEMS ((NUM_LEDS * BITS_PER_LED_CMD)) -// These values are determined by measuring pulse timing with logic analyzer and adjusting to match datasheet. -#define T0H 14 // 0 bit high time -#define T1H 52 // 1 bit high time -#define TL 52 // low time for either bit +// These values are determined by measuring pulse timing with logic analyzer and adjusting to match datasheet. +#define T0H 14 // 0 bit high time +#define T1H 52 // 1 bit high time +#define TL 52 // low time for either bit // sets a color based on RGB from 0..255 and a brightness in % from 0..100 -#define RGB(R,G,B,BR) (((G*BR)/100) << 16) | (((R*BR)/100) << 8) | ((B*BR)/100) +#define RGB(R, G, B, BR) (((G * BR) / 100) << 16) | (((R * BR) / 100) << 8) | ((B * BR) / 100) -#define RED RGB(255,0,0,10) -#define GREEN RGB(0,255,0,10) -#define BLUE RGB(0,0,255,10) -#define WHITE RGB(255,255,255,10) -#define YELLOW RGB(255,118,13,10) +#define RED RGB(255, 0, 0, 10) +#define GREEN RGB(0, 255, 0, 10) +#define BLUE RGB(0, 0, 255, 10) +#define WHITE RGB(255, 255, 255, 10) +#define YELLOW RGB(255, 118, 13, 10) struct led_state { uint32_t leds[NUM_LEDS]; @@ -46,46 +46,49 @@ void ws2812_write_leds(struct led_state new_state); /////////////////////////////////////////////////////////////////// -static const char TAG[] = "muse"; +static const char TAG[] = "muse"; static void (*battery_handler_chain)(float value, int cells); static void battery_svc(float value, int cells); static bool init(void); static void set_battery_led(float value); -const struct target_s target_muse = { .model = "muse", .init = init }; +const struct target_s target_muse = {.model = "muse", .init = init}; -static bool init(void) { - battery_handler_chain = battery_handler_svc; - battery_handler_svc = battery_svc; - - ws2812_control_init(); - float value = battery_value_svc(); - set_battery_led(value); - - ESP_LOGI(TAG, "Initializing for Muse %f", value); - - return true; +static bool init(void) { + battery_handler_chain = battery_handler_svc; + battery_handler_svc = battery_svc; + + ws2812_control_init(); + float value = battery_value_svc(); + set_battery_led(value); + + ESP_LOGI(TAG, "Initializing for Muse %f", value); + + return true; } -#define VGREEN 4.0 -#define VRED 3.6 +#define VGREEN 4.0 +#define VRED 3.6 static void set_battery_led(float value) { - struct led_state new_state; + struct led_state new_state; - if (value > VGREEN) new_state.leds[0] = GREEN; - else if (value < VRED) new_state.leds[0] = RED; - else new_state.leds[0] = YELLOW; + if(value > VGREEN) + new_state.leds[0] = GREEN; + else if(value < VRED) + new_state.leds[0] = RED; + else + new_state.leds[0] = YELLOW; - ws2812_write_leds(new_state); + ws2812_write_leds(new_state); } static void battery_svc(float value, int cells) { - set_battery_led(value); - ESP_LOGI(TAG, "Called for battery service with %f", value); + set_battery_led(value); + ESP_LOGI(TAG, "Called for battery service with %f", value); - if (battery_handler_chain) battery_handler_chain(value, cells); + if(battery_handler_chain) battery_handler_chain(value, cells); } // This is the buffer which the hw peripheral will access while pulsing the output pin @@ -93,43 +96,38 @@ rmt_item32_t led_data_buffer[LED_BUFFER_ITEMS]; void setup_rmt_data_buffer(struct led_state new_state); -void ws2812_control_init(void) -{ - rmt_channel = RMT_NEXT_TX_CHANNEL(); - rmt_config_t config; - config.rmt_mode = RMT_MODE_TX; - config.channel = rmt_channel; - config.gpio_num = LED_RMT_TX_GPIO; - config.mem_block_num = 3; - config.tx_config.loop_en = false; - config.tx_config.carrier_en = false; - config.tx_config.idle_output_en = true; - config.tx_config.idle_level = 0; - config.clk_div = 2; +void ws2812_control_init(void) { + rmt_channel = RMT_NEXT_TX_CHANNEL(); + rmt_config_t config; + config.rmt_mode = RMT_MODE_TX; + config.channel = rmt_channel; + config.gpio_num = LED_RMT_TX_GPIO; + config.mem_block_num = 3; + config.tx_config.loop_en = false; + config.tx_config.carrier_en = false; + config.tx_config.idle_output_en = true; + config.tx_config.idle_level = 0; + config.clk_div = 2; - ESP_ERROR_CHECK(rmt_config(&config)); - ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0)); - - ESP_LOGI(TAG, "LED wth ws2812 using gpio %d and channel %d", LED_RMT_TX_GPIO, rmt_channel); + ESP_ERROR_CHECK(rmt_config(&config)); + ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0)); + + ESP_LOGI(TAG, "LED wth ws2812 using gpio %d and channel %d", LED_RMT_TX_GPIO, rmt_channel); } void ws2812_write_leds(struct led_state new_state) { - setup_rmt_data_buffer(new_state); - rmt_write_items(rmt_channel, led_data_buffer, LED_BUFFER_ITEMS, false); + setup_rmt_data_buffer(new_state); + rmt_write_items(rmt_channel, led_data_buffer, LED_BUFFER_ITEMS, false); } -void setup_rmt_data_buffer(struct led_state new_state) -{ - for (uint32_t led = 0; led < NUM_LEDS; led++) { - uint32_t bits_to_send = new_state.leds[led]; - uint32_t mask = 1 << (BITS_PER_LED_CMD - 1); - for (uint32_t bit = 0; bit < BITS_PER_LED_CMD; bit++) { - uint32_t bit_is_set = bits_to_send & mask; - led_data_buffer[led * BITS_PER_LED_CMD + bit] = bit_is_set ? - (rmt_item32_t){{{T1H, 1, TL, 0}}} : - (rmt_item32_t){{{T0H, 1, TL, 0}}}; - mask >>= 1; +void setup_rmt_data_buffer(struct led_state new_state) { + for(uint32_t led = 0; led < NUM_LEDS; led++) { + uint32_t bits_to_send = new_state.leds[led]; + uint32_t mask = 1 << (BITS_PER_LED_CMD - 1); + for(uint32_t bit = 0; bit < BITS_PER_LED_CMD; bit++) { + uint32_t bit_is_set = bits_to_send & mask; + led_data_buffer[led * BITS_PER_LED_CMD + bit] = bit_is_set ? (rmt_item32_t){{{T1H, 1, TL, 0}}} : (rmt_item32_t){{{T0H, 1, TL, 0}}}; + mask >>= 1; + } } - } } - diff --git a/components/targets/targets.c b/components/targets/targets.c index 8aa5d669..67dbc01e 100644 --- a/components/targets/targets.c +++ b/components/targets/targets.c @@ -1,14 +1,15 @@ #include "string.h" #include "esp_log.h" #include "targets.h" -static const char * TAG = "targets"; -const struct target_s *target_set[] = { &target_muse, NULL }; +static const char* TAG = "targets"; +const struct target_s* target_set[] = {&target_muse, NULL}; -void target_init(char *target) { - ESP_LOGI(TAG,"Checking if target %s needs init",target); - for (int i = 0; *target && target_set[i]; i++) if (strcasestr(target_set[i]->model, target)) { - ESP_LOGI(TAG,"Initializing target %s ",target); - target_set[i]->init(); - break; - } +void target_init(char* target) { + ESP_LOGI(TAG, "Checking if target %s needs init", target); + for(int i = 0; *target && target_set[i]; i++) + if(strcasestr(target_set[i]->model, target)) { + ESP_LOGI(TAG, "Initializing target %s ", target); + target_set[i]->init(); + break; + } } diff --git a/components/targets/targets.h b/components/targets/targets.h index c6f870e1..f91d4245 100644 --- a/components/targets/targets.h +++ b/components/targets/targets.h @@ -8,15 +8,15 @@ * https://opensource.org/licenses/MIT * */ - -#pragma once - -#include "stddef.h" -#include "stdbool.h" + +#pragma once + +#include "stddef.h" +#include "stdbool.h" struct target_s { - char *model; - bool (*init)(void); + char* model; + bool (*init)(void); }; extern const struct target_s target_muse; diff --git a/components/telnet/telnet.c b/components/telnet/telnet.c index 6cc84850..c53838a2 100644 --- a/components/telnet/telnet.c +++ b/components/telnet/telnet.c @@ -74,14 +74,14 @@ static size_t process_logs(UBaseType_t bytes, bool make_room); static sys_telnet_config* telnet_svc = NULL; void init_telnet() { - if (!sys_services_config_TELNET(telnet_svc) || telnet_svc->enable == sys_telnet_output_SERIAL_ONLY) { + if(!sys_services_config_TELNET(telnet_svc) || telnet_svc->enable == sys_telnet_output_SERIAL_ONLY) { ESP_LOGI(TAG, "Telnet support disabled"); return; } ESP_LOGI(TAG, "Starting Telnet service"); ESP_LOGD(TAG, "Getting values from configuration"); - if (telnet_svc->block > 0) send_chunk = telnet_svc->block; - if (telnet_svc->block > 0) log_buf_size = telnet_svc->buffer; + if(telnet_svc->block > 0) send_chunk = telnet_svc->block; + if(telnet_svc->block > 0) log_buf_size = telnet_svc->buffer; ESP_LOGD(TAG, "Allocating memory for the ring buffer and storage. send_chunk: %d, log_buf_size: %d", send_chunk, log_buf_size); // Redirect the output to our telnet handler as soon as possible @@ -89,13 +89,13 @@ void init_telnet() { // All non-split ring buffer must have their memory alignment set to 32 bits. uint8_t* buffer_storage = (uint8_t*)heap_caps_malloc(sizeof(uint8_t) * log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct); - if (buf_handle == NULL || buffer_struct == NULL) { + if(buf_handle == NULL || buffer_struct == NULL) { ESP_LOGE(TAG, "Failed to create ring buffer for telnet!"); messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Failed to allocate memory for telnet buffer"); return; } - if (telnet_svc->enable == sys_telnet_output_TELNET) { + if(telnet_svc->enable == sys_telnet_output_TELNET) { ESP_LOGI(TAG, "***Redirecting log output to telnet"); } else { ESP_LOGI(TAG, "Instantiating telnet service"); @@ -107,7 +107,7 @@ void init_telnet() { vfs.open = &stdout_open; vfs.fstat = &stdout_fstat; - if (telnet_svc->enable == sys_telnet_output_TELNET_SERIAL) uart_fd = open("/dev/uart/0", O_RDWR); + if(telnet_svc->enable == sys_telnet_output_TELNET_SERIAL) uart_fd = open("/dev/uart/0", O_RDWR); ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL)); freopen("/dev/pkspstdout", "w", stdout); @@ -119,7 +119,7 @@ void init_telnet() { void start_telnet(void* pvParameter) { static bool isStarted = false; - if (isStarted || !bIsEnabled) return; + if(isStarted || !bIsEnabled) return; isStarted = true; @@ -136,19 +136,19 @@ static void telnet_task(void* data) { serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(23); - while (1) { + while(1) { serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) >= 0 && listen(serverSocket, 1) >= 0) break; + if(bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) >= 0 && listen(serverSocket, 1) >= 0) break; close(serverSocket); ESP_LOGI(TAG, "can't bind Telnet socket"); vTaskDelay(pdMS_TO_TICKS(1000)); } - while (1) { + while(1) { socklen_t len = sizeof(serverAddr); int sock = accept(serverSocket, (struct sockaddr*)&serverAddr, &len); - if (sock >= 0) { + if(sock >= 0) { partnerSocket = sock; ESP_LOGI(TAG, "We have a new client connection %d", sock); handle_telnet_conn(); @@ -169,7 +169,7 @@ static void telnet_task(void* data) { static void handle_telnet_events(telnet_t* thisTelnet, telnet_event_t* event, void* userData) { struct telnetUserData* telnetUserData = (struct telnetUserData*)userData; - switch (event->type) { + switch(event->type) { case TELNET_EV_SEND: send(telnetUserData->sockfd, event->data.buffer, event->data.size, 0); break; @@ -190,16 +190,16 @@ static size_t process_logs(UBaseType_t bytes, bool make_room) { vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &pending); // nothing to do or we can do - if (!partnerSocket || (make_room && log_buf_size - pending > bytes)) return pending; + if(!partnerSocket || (make_room && log_buf_size - pending > bytes)) return pending; // can't send more than what we have - if (bytes > pending) bytes = pending; + if(bytes > pending) bytes = pending; - while (bytes > 0) { + while(bytes > 0) { size_t size; char* item = (char*)xRingbufferReceiveUpTo(buf_handle, &size, pdMS_TO_TICKS(50), bytes); - if (!item || !partnerSocket) break; + if(!item || !partnerSocket) break; bytes -= size; telnet_send_text(tnHandle, item, size); @@ -225,7 +225,7 @@ static void handle_telnet_conn() { bool pending = true; - while (1) { + while(1) { fd_set rfds, wfds; struct timeval timeout = {0, 200 * 1000}; @@ -233,18 +233,18 @@ static void handle_telnet_conn() { FD_SET(partnerSocket, &rfds); FD_ZERO(&wfds); - if (pending) FD_SET(partnerSocket, &wfds); + if(pending) FD_SET(partnerSocket, &wfds); int res = select(partnerSocket + 1, &rfds, &wfds, NULL, &timeout); - if (res < 0) break; + if(res < 0) break; - if (FD_ISSET(partnerSocket, &rfds)) { + if(FD_ISSET(partnerSocket, &rfds)) { int len = recv(partnerSocket, pTelnetUserData->rxbuf, TELNET_RX_BUF, 0); - if (!len) break; + if(!len) break; telnet_recv(tnHandle, pTelnetUserData->rxbuf, len); } - if (FD_ISSET(partnerSocket, &wfds)) { + if(FD_ISSET(partnerSocket, &wfds)) { pending = process_logs(send_chunk, false) > 0; } else { pending = true; @@ -264,7 +264,7 @@ static void handle_telnet_conn() { // ******************* stdout/stderr Redirection to ringbuffer static ssize_t stdout_write(int fd, const void* data, size_t size) { // flush the buffer and send item - if (buf_handle) { + if(buf_handle) { process_logs(size, true); xRingbufferSend(buf_handle, data, size, 0); } diff --git a/components/telnet/telnet.h b/components/telnet/telnet.h index 255fa3d6..81d6342b 100644 --- a/components/telnet/telnet.h +++ b/components/telnet/telnet.h @@ -1,3 +1,3 @@ void init_telnet(); -void start_telnet(void * pvParameter); +void start_telnet(void* pvParameter); diff --git a/components/tools/bootstate.cpp b/components/tools/bootstate.cpp index 7f28367f..7ef8f18f 100644 --- a/components/tools/bootstate.cpp +++ b/components/tools/bootstate.cpp @@ -17,7 +17,7 @@ EXT_RAM_ATTR static bool restarting = false; uint32_t bootstate_read_counter(void) { return RebootCounter; } uint32_t bootstate_uptate_counter(int32_t xValue) { - if (RebootCounter > 100) { + if(RebootCounter > 100) { RebootCounter = 0; RecoveryRebootCounter = 0; } @@ -27,7 +27,7 @@ uint32_t bootstate_uptate_counter(int32_t xValue) { } void bootstate_handle_boot() { - if (ColdBootIndicatorFlag != 0xFACE) { + if(ColdBootIndicatorFlag != 0xFACE) { ESP_LOGI(TAG, "System is booting from power on."); cold_boot = true; ColdBootIndicatorFlag = 0xFACE; @@ -41,34 +41,32 @@ void bootstate_handle_boot() { running->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY ? "Factory" : "Application"); is_recovery_running = (running->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY); - if (!is_recovery_running) { + if(!is_recovery_running) { /* unscheduled restart (HW, Watchdog or similar) thus increment dynamic * counter then log current boot statistics as a warning */ uint32_t Counter = bootstate_uptate_counter(1); // increment counter ESP_LOGI(TAG, "Reboot counter=%u\n", Counter); - if (Counter == 5) { - guided_factory(); - } + if(Counter == 5) { guided_factory(); } } else { uint32_t Counter = bootstate_uptate_counter(1); // increment counter - if (RecoveryRebootCounter == 1 && Counter >= 5) { + if(RecoveryRebootCounter == 1 && Counter >= 5) { // First time we are rebooting in recovery after crashing messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "System was forced into recovery mode after crash likely caused by some bad " "configuration\n"); } ESP_LOGI(TAG, "Recovery Reboot counter=%u\n", Counter); - if (RecoveryRebootCounter == 5) { + if(RecoveryRebootCounter == 5) { ESP_LOGW(TAG, "System rebooted too many times. This could be an indication that " "configuration is corrupted. Erasing config."); - if (config_erase_config()) { + if(config_erase_config()) { config_raise_changed(true); guided_factory(); } else { ESP_LOGE(TAG, "Error erasing configuration"); } } - if (RecoveryRebootCounter > 5) { + if(RecoveryRebootCounter > 5) { messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "System was forced into recovery mode after crash likely caused by some bad " "configuration. Configuration was reset to factory.\n"); @@ -76,32 +74,26 @@ void bootstate_handle_boot() { } } esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) { - if (is_recovery_running) { - if (partition_subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) { - simple_restart(); - } + if(is_recovery_running) { + if(partition_subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) { simple_restart(); } } else { - if (partition_subtype != ESP_PARTITION_SUBTYPE_APP_FACTORY) { - simple_restart(); - } + if(partition_subtype != ESP_PARTITION_SUBTYPE_APP_FACTORY) { simple_restart(); } } esp_err_t err = ESP_OK; const esp_partition_t* partition; esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL); - if (it == NULL) { + if(it == NULL) { log_send_messaging(MESSAGING_ERROR, "Reboot failed. Partitions error"); } else { ESP_LOGD(TAG, "Found partition. Getting info."); partition = (esp_partition_t*)esp_partition_get(it); ESP_LOGD(TAG, "Releasing partition iterator"); esp_partition_iterator_release(it); - if (partition != NULL) { + if(partition != NULL) { log_send_messaging(MESSAGING_INFO, "Rebooting to %s", partition->label); err = esp_ota_set_boot_partition(partition); - if (err != ESP_OK) { - log_send_messaging(MESSAGING_ERROR, "Unable to select partition for reboot: %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { log_send_messaging(MESSAGING_ERROR, "Unable to select partition for reboot: %s", esp_err_to_name(err)); } } else { log_send_messaging(MESSAGING_ERROR, "partition type %u not found! Unable to reboot to recovery.", partition_subtype); } @@ -127,9 +119,9 @@ void simple_restart() { log_send_messaging(MESSAGING_WARNING, "Rebooting."); TimerHandle_t timer = xTimerCreate("reboot", 1, pdFALSE, nullptr, [](TimerHandle_t xTimer) { - if (!config_waitcommit()) { + if(!config_waitcommit()) { log_send_messaging(MESSAGING_WARNING, "Waiting for configuration to commit "); - ESP_LOGD(TAG,"Queuing restart asynchronously to ensure all events are flushed."); + ESP_LOGD(TAG, "Queuing restart asynchronously to ensure all events are flushed."); network_async_reboot(RESTART); return; } diff --git a/components/tools/bootstate.h b/components/tools/bootstate.h index 332e3e90..582d3068 100644 --- a/components/tools/bootstate.h +++ b/components/tools/bootstate.h @@ -29,8 +29,6 @@ extern "C" { #endif - - uint32_t bootstate_read_counter(void); /** diff --git a/components/tools/cpp_tools.cpp b/components/tools/cpp_tools.cpp index 0cf20f97..cdae71df 100644 --- a/components/tools/cpp_tools.cpp +++ b/components/tools/cpp_tools.cpp @@ -4,7 +4,7 @@ std::string trim(const std::string& str) { const size_t first = str.find_first_not_of(' '); - if (first == std::string::npos) { + if(first == std::string::npos) { // String contains only spaces or is empty return ""; } @@ -13,10 +13,8 @@ std::string trim(const std::string& str) { } std::string& toLowerStr(std::string& str) { - for (auto& c : str) { - if (c >= 'A' && c <= 'Z') { - c = c - 'A' + 'a'; - } + for(auto& c : str) { + if(c >= 'A' && c <= 'Z') { c = c - 'A' + 'a'; } } return str; } diff --git a/components/tools/operator.cpp b/components/tools/operator.cpp index 9234b7a8..eb843d18 100644 --- a/components/tools/operator.cpp +++ b/components/tools/operator.cpp @@ -1,12 +1,10 @@ #include #include -void* operator new(std::size_t count) { - return heap_caps_malloc(count, MALLOC_CAP_SPIRAM); -} +void* operator new(std::size_t count) { return heap_caps_malloc(count, MALLOC_CAP_SPIRAM); } -void operator delete(void* ptr) noexcept { - if (ptr) free(ptr); +void operator delete(void* ptr) noexcept { + if(ptr) free(ptr); } /* diff --git a/components/tools/perf_trace.h b/components/tools/perf_trace.h index 604901f6..23048c55 100644 --- a/components/tools/perf_trace.h +++ b/components/tools/perf_trace.h @@ -30,69 +30,86 @@ extern "C" { #endif #define PERF_MAX LONG_MAX -#define MIN_MAX_VAL(x) x==PERF_MAX?0:x -#define CURR_SAMPLE_RATE output.current_sample_rate>0?output.current_sample_rate:1 -#define FRAMES_TO_MS(f) (uint32_t)f*(uint32_t)1000/(uint32_t)(CURR_SAMPLE_RATE) +#define MIN_MAX_VAL(x) x == PERF_MAX ? 0 : x +#define CURR_SAMPLE_RATE output.current_sample_rate > 0 ? output.current_sample_rate : 1 +#define FRAMES_TO_MS(f) (uint32_t) f*(uint32_t)1000 / (uint32_t)(CURR_SAMPLE_RATE) #ifdef BYTES_TO_FRAME #define BYTES_TO_MS(b) FRAMES_TO_MS(BYTES_TO_FRAME(b)) #else -#define BYTES_TO_MS(b) FRAMES_TO_MS(b/BYTES_PER_FRAME) +#define BYTES_TO_MS(b) FRAMES_TO_MS(b / BYTES_PER_FRAME) #endif -#define SET_MIN_MAX(val,var) var=val; if(varmax_##var) max_##var=var; count_##var++; avgtot_##var+= var -#define SET_MIN_MAX_SIZED(val,var,siz) var=val; if(varmax_##var) max_##var=var; count_##var++; avgtot_##var+= var;size_##var=siz -#define RESET_MIN_MAX(var) min_##var=PERF_MAX; max_##var=0; avgtot_##var=0;count_##var=0;var=0;size_##var=0 -#define RESET_MIN_MAX_DURATION(var) min_##var=PERF_MAX; max_##var=0; avgtot_##var=0;count_##var=0;var=0 -#define DECLARE_MIN_MAX(var) static uint32_t min_##var = PERF_MAX, max_##var = 0, size_##var = 0, count_##var=0;static uint64_t avgtot_##var = 0; static uint32_t var=0 -#define DECLARE_MIN_MAX_DURATION(var) static uint32_t min_##var = PERF_MAX, max_##var = 0, count_##var=0; uint64_t avgtot_##var = 0; uint32_t var=0 -#define LINE_MIN_MAX_AVG(var) (uint32_t)(count_##var>0?avgtot_##var/count_##var:0) +#define SET_MIN_MAX(val, var) \ + var = val; \ + if(var < min_##var) min_##var = var; \ + if(var > max_##var) max_##var = var; \ + count_##var++; \ + avgtot_##var += var +#define SET_MIN_MAX_SIZED(val, var, siz) \ + var = val; \ + if(var < min_##var) min_##var = var; \ + if(var > max_##var) max_##var = var; \ + count_##var++; \ + avgtot_##var += var; \ + size_##var = siz +#define RESET_MIN_MAX(var) \ + min_##var = PERF_MAX; \ + max_##var = 0; \ + avgtot_##var = 0; \ + count_##var = 0; \ + var = 0; \ + size_##var = 0 +#define RESET_MIN_MAX_DURATION(var) \ + min_##var = PERF_MAX; \ + max_##var = 0; \ + avgtot_##var = 0; \ + count_##var = 0; \ + var = 0 +#define DECLARE_MIN_MAX(var) \ + static uint32_t min_##var = PERF_MAX, max_##var = 0, size_##var = 0, count_##var = 0; \ + static uint64_t avgtot_##var = 0; \ + static uint32_t var = 0 +#define DECLARE_MIN_MAX_DURATION(var) \ + static uint32_t min_##var = PERF_MAX, max_##var = 0, count_##var = 0; \ + uint64_t avgtot_##var = 0; \ + uint32_t var = 0 +#define LINE_MIN_MAX_AVG(var) (uint32_t)(count_##var > 0 ? avgtot_##var / count_##var : 0) -#define LINE_MIN_MAX_FORMAT_HEAD1 " +----------+----------+----------------+-----+----------------+" -#define LINE_MIN_MAX_FORMAT_HEAD2 " | max | min | average | | count |" -#define LINE_MIN_MAX_FORMAT_HEAD3 " | (bytes) | (bytes) | (bytes) | | |" -#define LINE_MIN_MAX_FORMAT_HEAD4 " +----------+----------+----------------+-----+----------------+" +#define LINE_MIN_MAX_FORMAT_HEAD1 " +----------+----------+----------------+-----+----------------+" +#define LINE_MIN_MAX_FORMAT_HEAD2 " | max | min | average | | count |" +#define LINE_MIN_MAX_FORMAT_HEAD3 " | (bytes) | (bytes) | (bytes) | | |" +#define LINE_MIN_MAX_FORMAT_HEAD4 " +----------+----------+----------------+-----+----------------+" #define LINE_MIN_MAX_FORMAT_FOOTER " +----------+----------+----------------+-----+----------------+" -#define LINE_MIN_MAX_FORMAT "%14s|%10u|%10u|%16u|%5u|%16u|" -#define LINE_MIN_MAX(name,var) name,\ - MIN_MAX_VAL(max_##var),\ - MIN_MAX_VAL(min_##var),\ - LINE_MIN_MAX_AVG(var),\ - size_##var!=0?100*LINE_MIN_MAX_AVG(var)/size_##var:0,\ - count_##var +#define LINE_MIN_MAX_FORMAT "%14s|%10u|%10u|%16u|%5u|%16u|" +#define LINE_MIN_MAX(name, var) \ + name, MIN_MAX_VAL(max_##var), MIN_MAX_VAL(min_##var), LINE_MIN_MAX_AVG(var), size_##var != 0 ? 100 * LINE_MIN_MAX_AVG(var) / size_##var : 0, \ + count_##var -#define LINE_MIN_MAX_FORMAT_STREAM "%14s|%10u|%10u|%16u|%5u|%16u|" -#define LINE_MIN_MAX_STREAM(name,var) name,\ - MIN_MAX_VAL(max_##var),\ - MIN_MAX_VAL(min_##var),\ - LINE_MIN_MAX_AVG(var),\ - size_##var!=0?100*LINE_MIN_MAX_AVG(var)/size_##var:0,\ - count_##var +#define LINE_MIN_MAX_FORMAT_STREAM "%14s|%10u|%10u|%16u|%5u|%16u|" +#define LINE_MIN_MAX_STREAM(name, var) \ + name, MIN_MAX_VAL(max_##var), MIN_MAX_VAL(min_##var), LINE_MIN_MAX_AVG(var), size_##var != 0 ? 100 * LINE_MIN_MAX_AVG(var) / size_##var : 0, \ + count_##var #define LINE_MIN_MAX_DURATION_FORMAT "%14s%10u|%10u|%11u|%11u|" -#define LINE_MIN_MAX_DURATION(name,var) name,MIN_MAX_VAL(max_##var),MIN_MAX_VAL(min_##var), LINE_MIN_MAX_AVG(var), count_##var +#define LINE_MIN_MAX_DURATION(name, var) name, MIN_MAX_VAL(max_##var), MIN_MAX_VAL(min_##var), LINE_MIN_MAX_AVG(var), count_##var +#define TIME_MEASUREMENT_START(x) x = esp_timer_get_time() +#define TIME_MEASUREMENT_GET(x) (esp_timer_get_time() - x) -#define TIME_MEASUREMENT_START(x) x=esp_timer_get_time() -#define TIME_MEASUREMENT_GET(x) (esp_timer_get_time()-x) - -#define TIMED_SECTION_START_MS_FORCE(x,force) if(hasTimeElapsed(x,force)) { -#define TIMED_SECTION_START_MS(x) if(hasTimeElapsed(x,false)){ -#define TIMED_SECTION_START_FORCE(x,force) TIMED_SECTION_START_MS(x * 1000UL,force) -#define TIMED_SECTION_START(x) TIMED_SECTION_START_MS(x * 1000UL) -#define TIMED_SECTION_END } -static inline bool hasTimeElapsed(time_t delayMS, bool bforce) -{ - static time_t lastTime=0; - struct timeval tv; - gettimeofday(&tv, NULL); - if (lastTime <= tv.tv_sec * 1000 + tv.tv_usec / 1000 ||bforce) - { - lastTime = tv.tv_sec * 1000 + tv.tv_usec / 1000 + delayMS; - return true; - } - else - return false; +#define TIMED_SECTION_START_MS_FORCE(x, force) if(hasTimeElapsed(x, force)) { +#define TIMED_SECTION_START_MS(x) if(hasTimeElapsed(x, false)) { +#define TIMED_SECTION_START_FORCE(x, force) TIMED_SECTION_START_MS(x * 1000UL, force) +#define TIMED_SECTION_START(x) TIMED_SECTION_START_MS(x * 1000UL) +#define TIMED_SECTION_END } +static inline bool hasTimeElapsed(time_t delayMS, bool bforce) { + static time_t lastTime = 0; + struct timeval tv; + gettimeofday(&tv, NULL); + if(lastTime <= tv.tv_sec * 1000 + tv.tv_usec / 1000 || bforce) { + lastTime = tv.tv_sec * 1000 + tv.tv_usec / 1000 + delayMS; + return true; + } else + return false; } #ifdef __cplusplus } #endif - diff --git a/components/tools/platform_esp32.h b/components/tools/platform_esp32.h index 2f291e30..af50334f 100644 --- a/components/tools/platform_esp32.h +++ b/components/tools/platform_esp32.h @@ -18,7 +18,7 @@ * along with this program. If not, see . * */ - + #pragma once #include "esp_pthread.h" @@ -27,7 +27,7 @@ #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases" #endif -extern bool console_push(const char * data, size_t size); +extern bool console_push(const char* data, size_t size); extern void console_start(); extern pthread_cond_t wifi_connect_suspend_cond; extern pthread_t wifi_connect_suspend_mutex; diff --git a/components/tools/tcpip_adapter_compat.h b/components/tools/tcpip_adapter_compat.h index 9bbb310f..3b4c958a 100644 --- a/components/tools/tcpip_adapter_compat.h +++ b/components/tools/tcpip_adapter_compat.h @@ -4,19 +4,13 @@ #include "esp_idf_version.h" #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) -typedef enum { - TCPIP_ADAPTER_IF_STA = 0, - TCPIP_ADAPTER_IF_AP = 1, - TCPIP_ADAPTER_IF_ETH = 2, - TCPIP_ADAPTER_IF_MAX -} tcpip_adapter_if_t; +typedef enum { TCPIP_ADAPTER_IF_STA = 0, TCPIP_ADAPTER_IF_AP = 1, TCPIP_ADAPTER_IF_ETH = 2, TCPIP_ADAPTER_IF_MAX } tcpip_adapter_if_t; typedef esp_netif_ip_info_t tcpip_adapter_ip_info_t; typedef esp_netif_dhcp_status_t tcpip_adapter_dhcp_status_t; -static inline esp_netif_t *tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if) -{ - switch (tcpip_if) { +static inline esp_netif_t* tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if) { + switch(tcpip_if) { case TCPIP_ADAPTER_IF_STA: return esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); case TCPIP_ADAPTER_IF_AP: @@ -28,27 +22,20 @@ static inline esp_netif_t *tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if) } } -static inline esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname) -{ - esp_netif_t *netif = tcpip_adapter_get_netif(tcpip_if); - if (!netif) { - return ESP_ERR_INVALID_ARG; - } +static inline esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char** hostname) { + esp_netif_t* netif = tcpip_adapter_get_netif(tcpip_if); + if(!netif) { return ESP_ERR_INVALID_ARG; } return esp_netif_get_hostname(netif, hostname); } -static inline bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if) -{ - esp_netif_t *netif = tcpip_adapter_get_netif(tcpip_if); +static inline bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if) { + esp_netif_t* netif = tcpip_adapter_get_netif(tcpip_if); return netif ? esp_netif_is_netif_up(netif) : false; } -static inline esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) -{ - esp_netif_t *netif = tcpip_adapter_get_netif(tcpip_if); - if (!netif) { - return ESP_ERR_INVALID_ARG; - } +static inline esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t* ip_info) { + esp_netif_t* netif = tcpip_adapter_get_netif(tcpip_if); + if(!netif) { return ESP_ERR_INVALID_ARG; } return esp_netif_get_ip_info(netif, ip_info); } #endif diff --git a/components/tools/test/test_tools.cpp b/components/tools/test/test_tools.cpp index ee99af55..6717eddf 100644 --- a/components/tools/test/test_tools.cpp +++ b/components/tools/test/test_tools.cpp @@ -91,8 +91,8 @@ TEST_CASE("Test Folder Wildcard Erase File ", "[tools]") { TEST_ASSERT_FALSE(get_file_info(&fileInfo, fullnamewc.str().c_str())); } -const std::vector testRestrictedFiles = {"defaults/config.bin", - "fonts/droid_sans_fb_11x13.bin", "targets/bureau-oled/config.bin", "www/favicon-32x32.png"}; +const std::vector testRestrictedFiles = { + "defaults/config.bin", "fonts/droid_sans_fb_11x13.bin", "targets/bureau-oled/config.bin", "www/favicon-32x32.png"}; TEST_CASE("Test _write_file Function", "[tools]") { init_spiffs(); @@ -187,8 +187,7 @@ TEST_CASE("Test _load_file and _get_file_info Functions", "[tools]") { TEST_ASSERT_TRUE(erase_path(testFileName, false)); // Test loading a non-existent file - uint8_t* nonExistentData = - (uint8_t*)load_file_psram(&loadedSize, "/spiffs/non_existent_file.bin"); + uint8_t* nonExistentData = (uint8_t*)load_file_psram(&loadedSize, "/spiffs/non_existent_file.bin"); TEST_ASSERT_NULL(nonExistentData); // Test getting information for a non-existent file @@ -247,7 +246,7 @@ static const std::vector testRestrictedPaths = { "/spiffs/www/index.html" // A restricted path }; TEST_CASE("Test is_restricted_path with restricted paths", "[tools]") { - for (const std::string& path : testRestrictedPaths) { + for(const std::string& path : testRestrictedPaths) { bool result = is_restricted_path(path.c_str()); TEST_ASSERT_TRUE(result); } @@ -260,7 +259,7 @@ TEST_CASE("Test is_restricted_path with non-restricted paths", "[tools]") { "/spiffs/allowed/otherfile.txt" // Not a restricted path }; - for (const std::string& path : nonRestrictedPaths) { + for(const std::string& path : nonRestrictedPaths) { bool result = is_restricted_path(path.c_str()); TEST_ASSERT_FALSE(result); } @@ -274,18 +273,16 @@ static const std::vector testWildcardPaths = { "/spiffs/fonts/*" // A path with wildcard }; TEST_CASE("Test is_restricted_path with wildcards (positive)", "[tools]") { - for (const std::string& path : testWildcardPaths) { + for(const std::string& path : testWildcardPaths) { bool result = is_restricted_path(path.c_str()); - if (!result) { - ESP_LOGE(TAG, "Unexpected result. File should be restricted: %s", path.c_str()); - } + if(!result) { ESP_LOGE(TAG, "Unexpected result. File should be restricted: %s", path.c_str()); } TEST_ASSERT_TRUE(result); } } TEST_CASE("Test Erase Restricted Path", "[erase_path]") { - for (const std::string& path : testRestrictedFiles) { + for(const std::string& path : testRestrictedFiles) { std::ostringstream fullfilename; fullfilename << "/spiffs/" << path; @@ -308,7 +305,7 @@ TEST_CASE("Test Erase Restricted Files with Wildcards", "[erase_path]") { // Get a list of restricted files based on restrictedPaths std::list restrictedFiles = get_files_list(std::string("/")); - for (const tools_file_entry_t& restrictedFile : restrictedFiles) { + for(const tools_file_entry_t& restrictedFile : restrictedFiles) { std::string fullfilename = "/" + restrictedFile.name; // Check if the file exists before erasing @@ -360,8 +357,8 @@ TEST_CASE("Create, Check, and Delete File in SPIFFS", "[spiffs]") { // Check if the new file is in the list and is unrestricted bool fileFound = false; bool fileUnrestricted = false; - for (const auto& fileEntry : fileList) { - if (fileEntry.name == testFileName) { + for(const auto& fileEntry : fileList) { + if(fileEntry.name == testFileName) { fileFound = true; fileUnrestricted = !fileEntry.restricted; break; @@ -376,8 +373,8 @@ TEST_CASE("Create, Check, and Delete File in SPIFFS", "[spiffs]") { fileFound = false; // Verify that the file no longer exists fileList = get_files_list("/spiffs"); - for (const auto& fileEntry : fileList) { - if (std::string(testFileName) == fileEntry.name) { + for(const auto& fileEntry : fileList) { + if(std::string(testFileName) == fileEntry.name) { fileFound = true; break; } diff --git a/components/tools/tools.c b/components/tools/tools.c index 795726a6..6d5e729a 100644 --- a/components/tools/tools.c +++ b/components/tools/tools.c @@ -91,11 +91,11 @@ static uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) { * @return The corresponding CP1252 character or 0x00 if there is no direct mapping. */ static uint8_t UNICODEtoCP1252(uint16_t chr) { - if (chr <= 0xff) + if(chr <= 0xff) return (chr & 0xff); else { ESP_LOGI(TAG, "some multi-byte %hx", chr); - switch (chr) { + switch(chr) { case 0x20ac: return 0x80; break; @@ -188,8 +188,8 @@ void utf8_decode(char* src) { uint32_t codep = 0, state = UTF8_ACCEPT; char* dst = src; - while (src && *src) { - if (!decode(&state, &codep, *src++)) *dst++ = UNICODEtoCP1252(codep); + while(src && *src) { + if(!decode(&state, &codep, *src++)) *dst++ = UNICODEtoCP1252(codep); } *dst = '\0'; @@ -202,7 +202,7 @@ void utf8_decode(char* src) { void* malloc_init_external(size_t sz) { void* ptr = NULL; ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (ptr == NULL) { + if(ptr == NULL) { ESP_LOGE(TAG, "malloc_init_external: unable to allocate %d bytes of PSRAM!", sz); } else { memset(ptr, 0x00, sz); @@ -213,7 +213,7 @@ void* malloc_init_external(size_t sz) { void* clone_obj_psram(void* source, size_t source_sz) { void* ptr = NULL; ptr = heap_caps_malloc(source_sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (ptr == NULL) { + if(ptr == NULL) { ESP_LOGE(TAG, "clone_obj_psram: unable to allocate %d bytes of PSRAM!", source_sz); } else { memcpy(ptr, source, source_sz); @@ -225,7 +225,7 @@ char* strdup_psram(const char* source) { void* ptr = NULL; size_t source_sz = strlen(source) + 1; ptr = heap_caps_malloc(source_sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (ptr == NULL) { + if(ptr == NULL) { ESP_LOGE(TAG, "strdup_psram: unable to allocate %d bytes of PSRAM! Cannot clone string %s", source_sz, source); } else { memset(ptr, 0x00, source_sz); @@ -277,7 +277,7 @@ BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName TaskHandle_t handle = xTaskCreateStatic(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, context->xStack, context->xTaskBuffer); // store context in TCB or free everything in case of failure - if (!handle) { + if(!handle) { free(context->xTaskBuffer); free(context->xStack); free(context); @@ -285,7 +285,7 @@ BaseType_t xTaskCreateEXTRAM(TaskFunction_t pvTaskCode, const char* const pcName vTaskSetThreadLocalStoragePointerAndDelCallback(handle, TASK_TLS_INDEX, context, (TlsDeleteCallbackFunction_t)task_cleanup); } - if (pxCreatedTask) *pxCreatedTask = handle; + if(pxCreatedTask) *pxCreatedTask = handle; return handle != NULL ? pdPASS : pdFAIL; } @@ -298,35 +298,33 @@ void vTaskDeleteEXTRAM(TaskHandle_t xTask) { } void dump_json_content(const char* prefix, cJSON* json, int level) { - if (!json) { + if(!json) { ESP_LOG_LEVEL(level, TAG, "%s: empty!", prefix); return; } char* output = cJSON_Print(json); - if (output) { - ESP_LOG_LEVEL(level, TAG, "%s: \n%s", prefix, output); - } + if(output) { ESP_LOG_LEVEL(level, TAG, "%s: \n%s", prefix, output); } FREE_AND_NULL(output); } const char* get_mem_flag_desc(int flags) { static char flagString[101]; memset(flagString, 0x00, sizeof(flagString)); - if (flags & MALLOC_CAP_EXEC) strcat(flagString, "EXEC "); - if (flags & MALLOC_CAP_32BIT) strcat(flagString, "32BIT "); - if (flags & MALLOC_CAP_8BIT) strcat(flagString, "8BIT "); - if (flags & MALLOC_CAP_DMA) strcat(flagString, "DMA "); - if (flags & MALLOC_CAP_PID2) strcat(flagString, "PID2 "); - if (flags & MALLOC_CAP_PID3) strcat(flagString, "PID3 "); - if (flags & MALLOC_CAP_PID4) strcat(flagString, "PID4 "); - if (flags & MALLOC_CAP_PID5) strcat(flagString, "PID5 "); - if (flags & MALLOC_CAP_PID6) strcat(flagString, "PID6 "); - if (flags & MALLOC_CAP_PID7) strcat(flagString, "PID7 "); - if (flags & MALLOC_CAP_SPIRAM) strcat(flagString, "SPIRAM "); - if (flags & MALLOC_CAP_INTERNAL) strcat(flagString, "INTERNAL "); - if (flags & MALLOC_CAP_DEFAULT) strcat(flagString, "DEFAULT "); - if (flags & MALLOC_CAP_IRAM_8BIT) strcat(flagString, "IRAM_8BIT "); - if (flags & MALLOC_CAP_RETENTION) strcat(flagString, "RETENTION "); + if(flags & MALLOC_CAP_EXEC) strcat(flagString, "EXEC "); + if(flags & MALLOC_CAP_32BIT) strcat(flagString, "32BIT "); + if(flags & MALLOC_CAP_8BIT) strcat(flagString, "8BIT "); + if(flags & MALLOC_CAP_DMA) strcat(flagString, "DMA "); + if(flags & MALLOC_CAP_PID2) strcat(flagString, "PID2 "); + if(flags & MALLOC_CAP_PID3) strcat(flagString, "PID3 "); + if(flags & MALLOC_CAP_PID4) strcat(flagString, "PID4 "); + if(flags & MALLOC_CAP_PID5) strcat(flagString, "PID5 "); + if(flags & MALLOC_CAP_PID6) strcat(flagString, "PID6 "); + if(flags & MALLOC_CAP_PID7) strcat(flagString, "PID7 "); + if(flags & MALLOC_CAP_SPIRAM) strcat(flagString, "SPIRAM "); + if(flags & MALLOC_CAP_INTERNAL) strcat(flagString, "INTERNAL "); + if(flags & MALLOC_CAP_DEFAULT) strcat(flagString, "DEFAULT "); + if(flags & MALLOC_CAP_IRAM_8BIT) strcat(flagString, "IRAM_8BIT "); + if(flags & MALLOC_CAP_RETENTION) strcat(flagString, "RETENTION "); return flagString; } @@ -335,7 +333,7 @@ const char* get_mem_flag_desc(int flags) { const char* get_mac_str() { uint8_t mac[6]; static char macStr[LOCAL_MAC_SIZE + 1] = {0}; - if (macStr[0] == 0) { + if(macStr[0] == 0) { ESP_LOGD(TAG, "calling esp_read_mac"); esp_read_mac((uint8_t*)&mac, ESP_MAC_WIFI_STA); ESP_LOGD(TAG, "Writing mac to string"); @@ -347,7 +345,7 @@ const char* get_mac_str() { char* alloc_get_string_with_mac(const char* val) { const char* macstr = get_mac_str(); char* fullvalue = (char*)malloc_init_external(strlen(val) + sizeof(macstr) + 1); - if (fullvalue) { + if(fullvalue) { strcpy(fullvalue, val); strcat(fullvalue, macstr); } else { @@ -369,9 +367,7 @@ char* alloc_get_fallback_unique_name() { #define FORMATTED_MAC_SIZE 20 char* alloc_get_formatted_mac_string(uint8_t mac[6]) { char* macStr = malloc_init_external(FORMATTED_MAC_SIZE); - if (macStr) { - snprintf(macStr, FORMATTED_MAC_SIZE, MACSTR, MAC2STR(mac)); - } + if(macStr) { snprintf(macStr, FORMATTED_MAC_SIZE, MACSTR, MAC2STR(mac)); } return macStr; } @@ -379,28 +375,16 @@ const char* str_or_unknown(const char* str) { return (str ? str : unknown_string const char* str_or_null(const char* str) { return (str ? str : null_string_placeholder); } esp_log_level_t get_log_level_from_char(char* level) { - if (!strcasecmp(level, "NONE")) { - return ESP_LOG_NONE; - } - if (!strcasecmp(level, "ERROR")) { - return ESP_LOG_ERROR; - } - if (!strcasecmp(level, "WARN")) { - return ESP_LOG_WARN; - } - if (!strcasecmp(level, "INFO")) { - return ESP_LOG_INFO; - } - if (!strcasecmp(level, "DEBUG")) { - return ESP_LOG_DEBUG; - } - if (!strcasecmp(level, "VERBOSE")) { - return ESP_LOG_VERBOSE; - } + if(!strcasecmp(level, "NONE")) { return ESP_LOG_NONE; } + if(!strcasecmp(level, "ERROR")) { return ESP_LOG_ERROR; } + if(!strcasecmp(level, "WARN")) { return ESP_LOG_WARN; } + if(!strcasecmp(level, "INFO")) { return ESP_LOG_INFO; } + if(!strcasecmp(level, "DEBUG")) { return ESP_LOG_DEBUG; } + if(!strcasecmp(level, "VERBOSE")) { return ESP_LOG_VERBOSE; } return ESP_LOG_WARN; } const char* get_log_level_desc(esp_log_level_t level) { - switch (level) { + switch(level) { case ESP_LOG_NONE: return "NONE"; break; diff --git a/components/tools/tools.h b/components/tools/tools.h index 3a37fa9e..24ad1adf 100644 --- a/components/tools/tools.h +++ b/components/tools/tools.h @@ -60,7 +60,7 @@ extern "C" { */ #ifndef STR_OR_ALT #ifdef __cplusplus -#define STR_OR_ALT(str, alt) (str!=nullptr ? str : alt) +#define STR_OR_ALT(str, alt) (str != nullptr ? str : alt) #else #define STR_OR_ALT(str, alt) (str ? str : alt) #endif @@ -98,7 +98,7 @@ extern "C" { */ #ifndef FREE_AND_NULL #define FREE_AND_NULL(x) \ - if (x) { \ + if(x) { \ free(x); \ x = NULL; \ } diff --git a/components/tools/tools_http_utils.c b/components/tools/tools_http_utils.c index 025412e6..54e955ee 100644 --- a/components/tools/tools_http_utils.c +++ b/components/tools/tools_http_utils.c @@ -26,8 +26,7 @@ static void http_downloader(void* arg); static esp_err_t http_event_handler(esp_http_client_event_t* evt); void http_download(char* url, size_t max, http_download_cb_t callback, void* context) { - http_context_t* http_context = - (http_context_t*)heap_caps_calloc(sizeof(http_context_t), 1, MALLOC_CAP_SPIRAM); + http_context_t* http_context = (http_context_t*)heap_caps_calloc(sizeof(http_context_t), 1, MALLOC_CAP_SPIRAM); esp_http_client_config_t config = { .url = url, @@ -40,8 +39,7 @@ void http_download(char* url, size_t max, http_download_cb_t callback, void* con http_context->max = max; http_context->client = esp_http_client_init(&config); - xTaskCreateEXTRAM( - http_downloader, "downloader", 8 * 1024, http_context, ESP_TASK_PRIO_MIN + 1, NULL); + xTaskCreateEXTRAM(http_downloader, "downloader", 8 * 1024, http_context, ESP_TASK_PRIO_MIN + 1, NULL); } static void http_downloader(void* arg) { @@ -57,17 +55,17 @@ static void http_downloader(void* arg) { static esp_err_t http_event_handler(esp_http_client_event_t* evt) { http_context_t* http_context = (http_context_t*)evt->user_data; - if (http_context->abort) return ESP_FAIL; + if(http_context->abort) return ESP_FAIL; - switch (evt->event_id) { + switch(evt->event_id) { case HTTP_EVENT_ERROR: http_context->callback(NULL, 0, http_context->user_context); http_context->abort = true; break; case HTTP_EVENT_ON_HEADER: - if (!strcasecmp(evt->header_key, "Content-Length")) { + if(!strcasecmp(evt->header_key, "Content-Length")) { size_t len = atoi(evt->header_value); - if (!len || len > http_context->max) { + if(!len || len > http_context->max) { ESP_LOGI(TAG, "content-length null or too large %zu / %zu", len, http_context->max); http_context->abort = true; } @@ -75,8 +73,8 @@ static esp_err_t http_event_handler(esp_http_client_event_t* evt) { break; case HTTP_EVENT_ON_DATA: { size_t len = esp_http_client_get_content_length(evt->client); - if (!http_context->data) { - if ((http_context->data = (uint8_t*)malloc(len)) == NULL) { + if(!http_context->data) { + if((http_context->data = (uint8_t*)malloc(len)) == NULL) { http_context->abort = true; ESP_LOGE(TAG, "failed to allocate memory for output buffer %zu", len); return ESP_FAIL; @@ -92,9 +90,9 @@ static esp_err_t http_event_handler(esp_http_client_event_t* evt) { case HTTP_EVENT_DISCONNECTED: { int mbedtls_err = 0; esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "HTTP download disconnect %d", err); - if (http_context->data) free(http_context->data); + if(http_context->data) free(http_context->data); http_context->callback(NULL, 0, http_context->user_context); return ESP_FAIL; } @@ -107,7 +105,6 @@ static esp_err_t http_event_handler(esp_http_client_event_t* evt) { return ESP_OK; } - /**************************************************************************************** * URL tools */ @@ -116,12 +113,12 @@ static inline char from_hex(char ch) { return isdigit(ch) ? ch - '0' : tolower(c void url_decode(char* url) { char *p, *src = strdup(url); - for (p = src; *src; url++) { + for(p = src; *src; url++) { *url = *src++; - if (*url == '%') { + if(*url == '%') { *url = from_hex(*src++) << 4; *url |= from_hex(*src++); - } else if (*url == '+') { + } else if(*url == '+') { *url = ' '; } } @@ -139,10 +136,9 @@ bool in_http_binding(pb_istream_t* stream, pb_byte_t* buf, size_t count) { httpd_req_t* req = (httpd_req_t*)stream->state; ESP_LOGV(TAG, "Reading %d bytes from http stream", count); int received = httpd_req_recv(req, (char*)buf, count); - if (received <= 0) { + if(received <= 0) { stream->errmsg = "Not all data received"; return false; } - return received==count; - + return received == count; } diff --git a/components/tools/tools_http_utils.h b/components/tools/tools_http_utils.h index 1a8e411a..16e79330 100644 --- a/components/tools/tools_http_utils.h +++ b/components/tools/tools_http_utils.h @@ -29,7 +29,6 @@ extern "C" { #endif - /** * @brief Type definition for a callback function used in HTTP download. * @@ -75,7 +74,6 @@ void url_decode(char* url); */ bool out_http_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count); - /** * @brief Callback function for input streaming with HTTP binding. * @@ -93,8 +91,6 @@ bool out_http_binding(pb_ostream_t* stream, const uint8_t* buf, size_t count); */ bool in_http_binding(pb_istream_t* stream, pb_byte_t* buf, size_t count); - - #ifdef __cplusplus } #endif diff --git a/components/tools/tools_spiffs_utils.cpp b/components/tools/tools_spiffs_utils.cpp index fecaba81..15b5f91a 100644 --- a/components/tools/tools_spiffs_utils.cpp +++ b/components/tools/tools_spiffs_utils.cpp @@ -20,11 +20,10 @@ const char* spiffs_base_path = "/spiffs"; // Struct to represent a file entry // list of reserved files that the system controls -const std::vector restrictedPaths = { - "/spiffs/defaults/*", "/spiffs/fonts/*", "/spiffs/targets/*", "/spiffs/www/*"}; +const std::vector restrictedPaths = {"/spiffs/defaults/*", "/spiffs/fonts/*", "/spiffs/targets/*", "/spiffs/www/*"}; void init_spiffs() { - if (initialized) { + if(initialized) { ESP_LOGV(TAG, "SPIFFS already initialized. returning"); return; } @@ -39,10 +38,10 @@ void init_spiffs() { // Note: esp_vfs_spiffs_register is an all-in-one convenience function. esp_err_t ret = esp_vfs_spiffs_register(spiffs_conf); - if (ret != ESP_OK) { - if (ret == ESP_FAIL) { + if(ret != ESP_OK) { + if(ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } else if (ret == ESP_ERR_NOT_FOUND) { + } else if(ret == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "Failed to find SPIFFS partition"); } else { ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); @@ -52,9 +51,8 @@ void init_spiffs() { size_t total = 0, used = 0; ret = esp_spiffs_info(spiffs_conf->partition_label, &total, &used); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", - esp_err_to_name(ret)); + if(ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", esp_err_to_name(ret)); esp_spiffs_format(spiffs_conf->partition_label); } else { ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); @@ -67,21 +65,21 @@ bool write_file(const uint8_t* data, size_t sz, const char* filename) { bool result = true; FILE* file = NULL; init_spiffs(); - if (data == NULL) { + if(data == NULL) { ESP_LOGE(TAG, "Cannot write file. Data not received"); return false; } - if (sz == 0) { + if(sz == 0) { ESP_LOGE(TAG, "Cannot write file. Data length 0"); return false; } file = fopen(filename, "wb"); - if (file == NULL) { + if(file == NULL) { ESP_LOGE(TAG, "Error opening %s for writing", filename); return false; } size_t written = fwrite(data, 1, sz, file); - if (written != sz) { + if(written != sz) { ESP_LOGE(TAG, "Write error. Wrote %d bytes of %d.", written, sz); result = false; } @@ -96,23 +94,18 @@ void* load_file(uint32_t memflags, size_t* sz, const char* filename) { size_t fsz = 0; file = fopen(filename, "rb"); - if (file == NULL) { - return data; - } + if(file == NULL) { return data; } fseek(file, 0, SEEK_END); fsz = ftell(file); fseek(file, 0, SEEK_SET); - if (fsz > 0) { - ESP_LOGD(TAG, "Allocating %d bytes to load file %s content with flags: %s ", fsz, filename, - get_mem_flag_desc(memflags)); + if(fsz > 0) { + ESP_LOGD(TAG, "Allocating %d bytes to load file %s content with flags: %s ", fsz, filename, get_mem_flag_desc(memflags)); data = (void*)heap_caps_calloc(1, fsz, memflags); - if (data == NULL) { + if(data == NULL) { ESP_LOGE(TAG, "Failed to allocate %d bytes to load file %s", fsz, filename); } else { fread(data, 1, fsz, file); - if (sz) { - *sz = fsz; - } + if(sz) { *sz = fsz; } } } else { ESP_LOGW(TAG, "File is empty. Nothing to read"); @@ -124,20 +117,18 @@ bool get_file_info(struct stat* pfileInfo, const char* filename) { // ensure that the spiffs is initialized struct stat fileInfo; init_spiffs(); - if (strlen(filename) == 0) { + if(strlen(filename) == 0) { ESP_LOGE(TAG, "Invalid file name"); return false; } ESP_LOGD(TAG, "Getting file info for %s", filename); bool result = false; // Use stat to fill the fileInfo structure - if (stat(filename, &fileInfo) != 0) { + if(stat(filename, &fileInfo) != 0) { ESP_LOGD(TAG, "File %s not found", filename); } else { result = true; - if (pfileInfo) { - memcpy(pfileInfo, &fileInfo, sizeof(fileInfo)); - } + if(pfileInfo) { memcpy(pfileInfo, &fileInfo, sizeof(fileInfo)); } ESP_LOGD(TAG, "File %s has %lu bytes", filename, fileInfo.st_size); } @@ -145,17 +136,15 @@ bool get_file_info(struct stat* pfileInfo, const char* filename) { } bool is_restricted_path(const char* filename) { - for (const auto& pattern : restrictedPaths) { - if (fnmatch(pattern.c_str(), filename, 0) == 0) { - return true; - } + for(const auto& pattern : restrictedPaths) { + if(fnmatch(pattern.c_str(), filename, 0) == 0) { return true; } } return false; } bool erase_path(const char* filename, bool restricted) { std::string full_path_with_wildcard = std::string(filename); - if (full_path_with_wildcard.empty()) { + if(full_path_with_wildcard.empty()) { ESP_LOGE(TAG, "Error constructing full path"); return false; } @@ -166,33 +155,31 @@ bool erase_path(const char* filename, bool restricted) { size_t lastSlashPos = full_path_with_wildcard.find_last_of('/'); std::string dirpath = full_path_with_wildcard.substr(0, lastSlashPos); std::string wildcard = full_path_with_wildcard.substr(lastSlashPos + 1); - ESP_LOGD(TAG, "Last slash pos: %d, dirpath: %s, wildcard %s ", lastSlashPos, dirpath.c_str(), - wildcard.c_str()); + ESP_LOGD(TAG, "Last slash pos: %d, dirpath: %s, wildcard %s ", lastSlashPos, dirpath.c_str(), wildcard.c_str()); DIR* dir = opendir(dirpath.empty() ? "." : dirpath.c_str()); - if (!dir) { + if(!dir) { ESP_LOGE(TAG, "Error opening directory"); return false; } bool result = false; struct dirent* ent; - while ((ent = readdir(dir)) != NULL) { - if (fnmatch(wildcard.c_str(), ent->d_name, 0) == 0) { + while((ent = readdir(dir)) != NULL) { + if(fnmatch(wildcard.c_str(), ent->d_name, 0) == 0) { std::string fullfilename = dirpath + "/" + ent->d_name; // Check if the file is restricted - if (restricted && is_restricted_path(fullfilename.c_str())) { + if(restricted && is_restricted_path(fullfilename.c_str())) { ESP_LOGW(TAG, "Skipping restricted file %s", fullfilename.c_str()); continue; } ESP_LOGW(TAG, "Deleting file %s", fullfilename.c_str()); - if (remove(fullfilename.c_str()) != 0) { + if(remove(fullfilename.c_str()) != 0) { ESP_LOGE(TAG, "Error deleting file %s", fullfilename.c_str()); } else { result = true; } } else { - ESP_LOGV( - TAG, "%s does not match file pattern to delete: %s", ent->d_name, wildcard.c_str()); + ESP_LOGV(TAG, "%s does not match file pattern to delete: %s", ent->d_name, wildcard.c_str()); } } @@ -206,27 +193,24 @@ void printFileEntry(const tools_file_entry_t& entry) { double size; // Format the size - if (entry.type == 'F') { - if (entry.size < 1024) { // less than 1 KB + if(entry.type == 'F') { + if(entry.size < 1024) { // less than 1 KB size = entry.size; suffix = " B"; - printf("%c %10.0f%s %-80s%4s\n", entry.type, size, suffix, entry.name.c_str(), - entry.restricted ? "X" : "-"); + printf("%c %10.0f%s %-80s%4s\n", entry.type, size, suffix, entry.name.c_str(), entry.restricted ? "X" : "-"); } else { - if (entry.size < 1024 * 1024) { // 1 KB to <1 MB + if(entry.size < 1024 * 1024) { // 1 KB to <1 MB size = entry.size / 1024; suffix = " KB"; } else { // 1 MB and above size = entry.size / (1024 * 1024); suffix = " MB"; } - printf("%c %10.0f%s %-80s%4s\n", entry.type, size, suffix, entry.name.c_str(), - entry.restricted ? "X" : "-"); + printf("%c %10.0f%s %-80s%4s\n", entry.type, size, suffix, entry.name.c_str(), entry.restricted ? "X" : "-"); } } else { - printf("%c - %-80s%4s\n", entry.type, entry.name.c_str(), - entry.restricted ? "X" : "-"); + printf("%c - %-80s%4s\n", entry.type, entry.name.c_str(), entry.restricted ? "X" : "-"); } } @@ -244,8 +228,8 @@ void listFiles(const char* path_requested_char) { uint64_t total = 0; int nfiles = 0; - for (auto& e : filesList) { - if (e.type == 'F') { + for(auto& e : filesList) { + if(e.type == 'F') { total += e.size; nfiles++; } @@ -253,9 +237,7 @@ void listFiles(const char* path_requested_char) { } printf("---------------------------------------------------------------------------------------" "---------------\n"); - if (total > 0) { - printf("Total : %lu bytes in %d file(s)\n", (unsigned long)total, nfiles); - } + if(total > 0) { printf("Total : %lu bytes in %d file(s)\n", (unsigned long)total, nfiles); } size_t tot = 0, used = 0; esp_spiffs_info(NULL, &tot, &used); @@ -288,17 +270,17 @@ std::list get_files_list(const std::string& path_requested) std::string prefix = (path_requested.back() != '/' ? path_requested + "/" : path_requested); DIR* dir = opendir(path_requested.c_str()); - if (!dir) { + if(!dir) { ESP_LOGE(TAG, "Error opening directory %s ", path_requested.c_str()); return fileList; } - while ((ent = readdir(dir)) != NULL) { + while((ent = readdir(dir)) != NULL) { tools_file_entry_t fileEntry; fileEntry.name = prefix + ent->d_name; fileEntry.type = (ent->d_type == DT_REG) ? 'F' : 'D'; fileEntry.restricted = is_restricted_path(fileEntry.name.c_str()); - if (stat(fileEntry.name.c_str(), &sb) == -1) { + if(stat(fileEntry.name.c_str(), &sb) == -1) { ESP_LOGE(TAG, "Ignoring file %s ", fileEntry.name.c_str()); continue; } @@ -307,14 +289,12 @@ std::list get_files_list(const std::string& path_requested) // Extract all parent directory names size_t pos = 0; - while ((pos = fileEntry.name.find('/', pos + 1)) != std::string::npos) { - directoryNames.insert(fileEntry.name.substr(0, pos)); - } + while((pos = fileEntry.name.find('/', pos + 1)) != std::string::npos) { directoryNames.insert(fileEntry.name.substr(0, pos)); } } closedir(dir); // Add directories to the file list - for (const auto& dirName : directoryNames) { + for(const auto& dirName : directoryNames) { tools_file_entry_t dirEntry; dirEntry.name = dirName; dirEntry.type = 'D'; // Mark as directory @@ -322,12 +302,10 @@ std::list get_files_list(const std::string& path_requested) } // Sort the list by directory/file name - fileList.sort( - [](const tools_file_entry_t& a, const tools_file_entry_t& b) { return a.name < b.name; }); + fileList.sort([](const tools_file_entry_t& a, const tools_file_entry_t& b) { return a.name < b.name; }); // Remove duplicates - fileList.unique( - [](const tools_file_entry_t& a, const tools_file_entry_t& b) { return a.name == b.name; }); + fileList.unique([](const tools_file_entry_t& a, const tools_file_entry_t& b) { return a.name == b.name; }); return fileList; } @@ -335,13 +313,13 @@ bool cat_file(const char* filename) { size_t sz; uint8_t* content = (uint8_t*)load_file_psram(&sz, filename); - if (content == NULL) { + if(content == NULL) { printf("Failed to load file\n"); return false; } - for (size_t i = 0; i < sz; i++) { - if (isprint(content[i])) { + for(size_t i = 0; i < sz; i++) { + if(isprint(content[i])) { printf("%c", content[i]); // Print as a character } else { printf("\\x%02x", content[i]); // Print as hexadecimal @@ -354,14 +332,13 @@ bool cat_file(const char* filename) { } bool dump_data(const uint8_t* pData, size_t length) { - if (pData == NULL && length == 0) { - printf("%s/%s\n", pData == nullptr ? "Invalid Data" : "Data OK", - length == 0 ? "Invalid Length" : "Length OK"); + if(pData == NULL && length == 0) { + printf("%s/%s\n", pData == nullptr ? "Invalid Data" : "Data OK", length == 0 ? "Invalid Length" : "Length OK"); return false; } - for (size_t i = 0; i < length; i++) { - if (isprint((char)pData[i])) { + for(size_t i = 0; i < length; i++) { + if(isprint((char)pData[i])) { printf("%c", (char)pData[i]); // Print as a character } else { printf("\\x%02x", (char)pData[i]); // Print as hexadecimal @@ -376,7 +353,7 @@ bool dump_structure(const pb_msgdesc_t* fields, const void* src_struct) { try { std::vector encodedData = System::PBHelper::EncodeData(fields, src_struct); return dump_data(encodedData.data(), encodedData.size()); - } catch (const std::runtime_error& e) { + } catch(const std::runtime_error& e) { ESP_LOGE(TAG, "Error in dump_structure: %s", e.what()); return false; } diff --git a/components/tools/trace.c b/components/tools/trace.c index 74270e8e..4faa334b 100644 --- a/components/tools/trace.c +++ b/components/tools/trace.c @@ -13,29 +13,28 @@ #include "tools.h" #include "trace.h" - static const char TAG[] = "TRACE"; typedef struct mem_usage_trace_for_thread { TaskHandle_t task; size_t malloc_int_last; - size_t malloc_spiram_last; + size_t malloc_spiram_last; size_t malloc_dma_last; - const char *name; + const char* name; SLIST_ENTRY(mem_usage_trace_for_thread) next; } mem_usage_trace_for_thread_t; static EXT_RAM_ATTR SLIST_HEAD(memtrace, mem_usage_trace_for_thread) s_memtrace; -mem_usage_trace_for_thread_t* memtrace_get_thread_entry(TaskHandle_t task) { +mem_usage_trace_for_thread_t* memtrace_get_thread_entry(TaskHandle_t task) { if(!task) { ESP_LOGE(TAG, "memtrace_get_thread_entry: task is NULL"); return NULL; } - ESP_LOGD(TAG,"Looking for task %s",STR_OR_ALT(pcTaskGetName(task ), "unknown")); + ESP_LOGD(TAG, "Looking for task %s", STR_OR_ALT(pcTaskGetName(task), "unknown")); mem_usage_trace_for_thread_t* it; SLIST_FOREACH(it, &s_memtrace, next) { - if ( it->task == task ) { - ESP_LOGD(TAG,"Found task %s",STR_OR_ALT(pcTaskGetName(task ), "unknown")); + if(it->task == task) { + ESP_LOGD(TAG, "Found task %s", STR_OR_ALT(pcTaskGetName(task), "unknown")); return it; } } diff --git a/components/tools/trace.h b/components/tools/trace.h index 18a3644c..e00c895c 100644 --- a/components/tools/trace.h +++ b/components/tools/trace.h @@ -28,14 +28,10 @@ extern "C" { #endif #ifdef CONFIG_HEAP_TRACING #define TRACE_INIT \ - if (!is_recovery_running) { \ - ESP_ERROR_CHECK(heap_trace_init_tohost()); \ - } + if(!is_recovery_running) { ESP_ERROR_CHECK(heap_trace_init_tohost()); } #define TRACE_START \ - if (!is_recovery_running) { \ - ESP_ERROR_CHECK(heap_trace_start(HEAP_TRACE_ALL)); \ - } \ - #define TRACE_STOP if (!is_recovery_running) { ESP_ERROR_CHECK(heap_trace_stop()); } + if(!is_recovery_running) { ESP_ERROR_CHECK(heap_trace_start(HEAP_TRACE_ALL)); } \ + #define TRACE_STOP if(!is_recovery_running) { ESP_ERROR_CHECK(heap_trace_stop()); } #else #define TRACE_START #define TRACE_STOP diff --git a/components/wifi-manager/dns_server.c b/components/wifi-manager/dns_server.c index 964a6624..4bfc3379 100644 --- a/components/wifi-manager/dns_server.c +++ b/components/wifi-manager/dns_server.c @@ -61,32 +61,29 @@ static const char TAG[] = "dns_server"; static TaskHandle_t task_dns_server = NULL; int socket_fd; -void dns_server_start(esp_netif_t * netif) { - xTaskCreateEXTRAM(&dns_server, "dns_server", 3072, (void *)netif, ESP_TASK_PRIO_MIN+5, &task_dns_server); +void dns_server_start(esp_netif_t* netif) { + xTaskCreateEXTRAM(&dns_server, "dns_server", 3072, (void*)netif, ESP_TASK_PRIO_MIN + 5, &task_dns_server); } -void dns_server_stop(){ - if(task_dns_server){ - vTaskDelete(task_dns_server); - close(socket_fd); - task_dns_server = NULL; - } - +void dns_server_stop() { + if(task_dns_server) { + vTaskDelete(task_dns_server); + close(socket_fd); + task_dns_server = NULL; + } } - -void dns_server(void *pvParameters) { +void dns_server(void* pvParameters) { struct sockaddr_in sa, ra; esp_err_t esp_err = ESP_OK; - esp_netif_t * netif = (esp_netif_t * )pvParameters; + esp_netif_t* netif = (esp_netif_t*)pvParameters; /* Set redirection DNS hijack to the access point IP */ ip4_addr_t ip_resolved; inet_pton(AF_INET, platform->net.ap.ip.ip, &ip_resolved); - /* Create UDP socket */ socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (socket_fd < 0){ + if(socket_fd < 0) { ESP_LOGE(TAG, "Failed to create socket"); exit(0); } @@ -94,15 +91,15 @@ void dns_server(void *pvParameters) { /* Bind to port 53 (typical DNS Server port) */ esp_netif_ip_info_t ip_info; - esp_err = esp_netif_get_ip_info(netif,&ip_info); - if(esp_err!=ESP_OK) { + esp_err = esp_netif_get_ip_info(netif, &ip_info); + if(esp_err != ESP_OK) { ESP_LOGE(TAG, "Failed to get adapter info for udp: %s", esp_err_to_name(esp_err)); exit(1); } ra.sin_family = AF_INET; ra.sin_addr.s_addr = ip_info.ip.addr; ra.sin_port = htons(53); - if (bind(socket_fd, (struct sockaddr *)&ra, sizeof(struct sockaddr_in)) == -1) { + if(bind(socket_fd, (struct sockaddr*)&ra, sizeof(struct sockaddr_in)) == -1) { ESP_LOGE(TAG, "Failed to bind to 53/udp"); close(socket_fd); exit(1); @@ -112,10 +109,10 @@ void dns_server(void *pvParameters) { socklen_t client_len; client_len = sizeof(client); int length; - uint8_t data[DNS_QUERY_MAX_SIZE]; /* dns query buffer */ + uint8_t data[DNS_QUERY_MAX_SIZE]; /* dns query buffer */ uint8_t response[DNS_ANSWER_MAX_SIZE]; /* dns response buffer */ - char ip_address[INET_ADDRSTRLEN]; /* buffer to store IPs as text. This is only used for debug and serves no other purpose */ - char *domain; /* This is only used for debug and serves no other purpose */ + char ip_address[INET_ADDRSTRLEN]; /* buffer to store IPs as text. This is only used for debug and serves no other purpose */ + char* domain; /* This is only used for debug and serves no other purpose */ int err; ESP_LOGI(TAG, "DNS Server listening on 53/udp"); @@ -123,65 +120,58 @@ void dns_server(void *pvParameters) { /* Start loop to process DNS requests */ for(;;) { - memset(data, 0x00, sizeof(data)); /* reset buffer */ - length = recvfrom(socket_fd, data, sizeof(data), 0, (struct sockaddr *)&client, &client_len); /* read udp request */ + memset(data, 0x00, sizeof(data)); /* reset buffer */ + length = recvfrom(socket_fd, data, sizeof(data), 0, (struct sockaddr*)&client, &client_len); /* read udp request */ /*if the query is bigger than the buffer size we simply ignore it. This case should only happen in case of multiple * queries within the same DNS packet and is not supported by this simple DNS hijack. */ - if ( length > 0 && ((length + sizeof(dns_answer_t)-1) < DNS_ANSWER_MAX_SIZE) ) { + if(length > 0 && ((length + sizeof(dns_answer_t) - 1) < DNS_ANSWER_MAX_SIZE)) { - data[length] = '\0'; /*in case there's a bogus domain name that isn't null terminated */ + data[length] = '\0'; /*in case there's a bogus domain name that isn't null terminated */ /* Generate header message */ memcpy(response, data, sizeof(dns_header_t)); - dns_header_t *dns_header = (dns_header_t*)response; - dns_header->QR = 1; /*response bit */ - dns_header->OPCode = DNS_OPCODE_QUERY; /* no support for other type of response */ - dns_header->AA = 1; /*authoritative answer */ + dns_header_t* dns_header = (dns_header_t*)response; + dns_header->QR = 1; /*response bit */ + dns_header->OPCode = DNS_OPCODE_QUERY; /* no support for other type of response */ + dns_header->AA = 1; /*authoritative answer */ dns_header->RCode = DNS_REPLY_CODE_NO_ERROR; /* no error */ - dns_header->TC = 0; /*no truncation */ - dns_header->RD = 0; /*no recursion */ - dns_header->ANCount = dns_header->QDCount; /* set answer count = question count -- duhh! */ - dns_header->NSCount = 0x0000; /* name server resource records = 0 */ - dns_header->ARCount = 0x0000; /* resource records = 0 */ - + dns_header->TC = 0; /*no truncation */ + dns_header->RD = 0; /*no recursion */ + dns_header->ANCount = dns_header->QDCount; /* set answer count = question count -- duhh! */ + dns_header->NSCount = 0x0000; /* name server resource records = 0 */ + dns_header->ARCount = 0x0000; /* resource records = 0 */ /* copy the rest of the query in the response */ memcpy(response + sizeof(dns_header_t), data + sizeof(dns_header_t), length - sizeof(dns_header_t)); - /* extract domain name and request IP for debug */ inet_ntop(AF_INET, &(client.sin_addr), ip_address, INET_ADDRSTRLEN); - domain = (char*) &data[sizeof(dns_header_t) + 1]; - for(char* c=domain; *c != '\0'; c++){ - if(*c < ' ' || *c > 'z') *c = '.'; /* technically we should test if the first two bits are 00 (e.g. if( (*c & 0xC0) == 0x00) *c = '.') but this makes the code a lot more readable */ + domain = (char*)&data[sizeof(dns_header_t) + 1]; + for(char* c = domain; *c != '\0'; c++) { + if(*c < ' ' || *c > 'z') + *c = + '.'; /* technically we should test if the first two bits are 00 (e.g. if( (*c & 0xC0) == 0x00) *c = '.') but this makes the code a lot more readable */ } ESP_LOGD(TAG, "Replying to DNS request for %s from %s", domain, ip_address); - /* create DNS answer at the end of the query*/ - dns_answer_t *dns_answer = (dns_answer_t*)&response[length]; - dns_answer->NAME = __bswap_16(0xC00C); /* This is a pointer to the beginning of the question. As per DNS standard, first two bits must be set to 11 for some odd reason hence 0xC0 */ + dns_answer_t* dns_answer = (dns_answer_t*)&response[length]; + dns_answer->NAME = __bswap_16( + 0xC00C); /* This is a pointer to the beginning of the question. As per DNS standard, first two bits must be set to 11 for some odd reason hence 0xC0 */ dns_answer->TYPE = __bswap_16(DNS_ANSWER_TYPE_A); dns_answer->CLASS = __bswap_16(DNS_ANSWER_CLASS_IN); - dns_answer->TTL = (uint32_t)0x00000000; /* no caching. Avoids DNS poisoning since this is a DNS hijack */ + dns_answer->TTL = (uint32_t)0x00000000; /* no caching. Avoids DNS poisoning since this is a DNS hijack */ dns_answer->RDLENGTH = __bswap_16(0x0004); /* 4 byte => size of an ipv4 address */ dns_answer->RDATA = ip_resolved.addr; - err = sendto(socket_fd, response, length+sizeof(dns_answer_t), 0, (struct sockaddr *)&client, client_len); - if (err < 0) { - ESP_LOGE(TAG, "UDP sendto failed: %d", err); - } + err = sendto(socket_fd, response, length + sizeof(dns_answer_t), 0, (struct sockaddr*)&client, client_len); + if(err < 0) { ESP_LOGE(TAG, "UDP sendto failed: %d", err); } } taskYIELD(); /* allows the freeRTOS scheduler to take over if needed. DNS daemon should not be taxing on the system */ - } close(socket_fd); - vTaskDelete ( NULL ); + vTaskDelete(NULL); } - - - - diff --git a/components/wifi-manager/dns_server.h b/components/wifi-manager/dns_server.h index 63246f08..fdb60726 100644 --- a/components/wifi-manager/dns_server.h +++ b/components/wifi-manager/dns_server.h @@ -37,106 +37,86 @@ Contains the freeRTOS task for the DNS server that processes the requests. #include "squeezelite-ota.h" #include "esp_netif.h" - #ifdef __cplusplus extern "C" { #endif - /** 12 byte header, 64 byte domain name, 4 byte qtype/qclass. This NOT compliant with the RFC, but it's good enough for a captive portal * if a DNS query is too big it just wont be processed. */ -#define DNS_QUERY_MAX_SIZE 80 +#define DNS_QUERY_MAX_SIZE 80 /** Query + 2 byte ptr, 2 byte type, 2 byte class, 4 byte TTL, 2 byte len, 4 byte data */ -#define DNS_ANSWER_MAX_SIZE (DNS_QUERY_MAX_SIZE+16) - +#define DNS_ANSWER_MAX_SIZE (DNS_QUERY_MAX_SIZE + 16) /** * @brief RCODE values used in a DNS header message */ typedef enum dns_reply_code_t { - DNS_REPLY_CODE_NO_ERROR = 0, - DNS_REPLY_CODE_FORM_ERROR = 1, - DNS_REPLY_CODE_SERVER_FAILURE = 2, - DNS_REPLY_CODE_NON_EXISTANT_DOMAIN = 3, - DNS_REPLY_CODE_NOT_IMPLEMENTED = 4, - DNS_REPLY_CODE_REFUSED = 5, - DNS_REPLY_CODE_YXDOMAIN = 6, - DNS_REPLY_CODE_YXRRSET = 7, - DNS_REPLY_CODE_NXRRSET = 8 -}dns_reply_code_t; - - + DNS_REPLY_CODE_NO_ERROR = 0, + DNS_REPLY_CODE_FORM_ERROR = 1, + DNS_REPLY_CODE_SERVER_FAILURE = 2, + DNS_REPLY_CODE_NON_EXISTANT_DOMAIN = 3, + DNS_REPLY_CODE_NOT_IMPLEMENTED = 4, + DNS_REPLY_CODE_REFUSED = 5, + DNS_REPLY_CODE_YXDOMAIN = 6, + DNS_REPLY_CODE_YXRRSET = 7, + DNS_REPLY_CODE_NXRRSET = 8 +} dns_reply_code_t; /** * @brief OPCODE values used in a DNS header message */ -typedef enum dns_opcode_code_t { - DNS_OPCODE_QUERY = 0, - DNS_OPCODE_IQUERY = 1, - DNS_OPCODE_STATUS = 2 -}dns_opcode_code_t; - - +typedef enum dns_opcode_code_t { DNS_OPCODE_QUERY = 0, DNS_OPCODE_IQUERY = 1, DNS_OPCODE_STATUS = 2 } dns_opcode_code_t; /** * @brief Represents a 12 byte DNS header. * __packed__ is needed to prevent potential unwanted memory alignments */ -typedef struct __attribute__((__packed__)) dns_header_t{ - uint16_t ID; // identification number - uint8_t RD : 1; // recursion desired - uint8_t TC : 1; // truncated message - uint8_t AA : 1; // authoritive answer - uint8_t OPCode : 4; // message_type - uint8_t QR : 1; // query/response flag - uint8_t RCode : 4; // response code - uint8_t Z : 3; // its z! reserved - uint8_t RA : 1; // recursion available - uint16_t QDCount; // number of question entries - uint16_t ANCount; // number of answer entries - uint16_t NSCount; // number of authority entries - uint16_t ARCount; // number of resource entries -}dns_header_t; - - +typedef struct __attribute__((__packed__)) dns_header_t { + uint16_t ID; // identification number + uint8_t RD : 1; // recursion desired + uint8_t TC : 1; // truncated message + uint8_t AA : 1; // authoritive answer + uint8_t OPCode : 4; // message_type + uint8_t QR : 1; // query/response flag + uint8_t RCode : 4; // response code + uint8_t Z : 3; // its z! reserved + uint8_t RA : 1; // recursion available + uint16_t QDCount; // number of question entries + uint16_t ANCount; // number of answer entries + uint16_t NSCount; // number of authority entries + uint16_t ARCount; // number of resource entries +} dns_header_t; typedef enum dns_answer_type_t { - DNS_ANSWER_TYPE_A = 1, - DNS_ANSWER_TYPE_NS = 2, - DNS_ANSWER_TYPE_CNAME = 5, - DNS_ANSWER_TYPE_SOA = 6, - DNS_ANSWER_TYPE_WKS = 11, - DNS_ANSWER_TYPE_PTR = 12, - DNS_ANSWER_TYPE_MX = 15, - DNS_ANSWER_TYPE_SRV = 33, - DNS_ANSWER_TYPE_AAAA = 28 -}dns_answer_type_t; + DNS_ANSWER_TYPE_A = 1, + DNS_ANSWER_TYPE_NS = 2, + DNS_ANSWER_TYPE_CNAME = 5, + DNS_ANSWER_TYPE_SOA = 6, + DNS_ANSWER_TYPE_WKS = 11, + DNS_ANSWER_TYPE_PTR = 12, + DNS_ANSWER_TYPE_MX = 15, + DNS_ANSWER_TYPE_SRV = 33, + DNS_ANSWER_TYPE_AAAA = 28 +} dns_answer_type_t; -typedef enum dns_answer_class_t { - DNS_ANSWER_CLASS_IN = 1 -}dns_answer_class_t; +typedef enum dns_answer_class_t { DNS_ANSWER_CLASS_IN = 1 } dns_answer_class_t; +typedef struct __attribute__((__packed__)) dns_answer_t { + uint16_t NAME; /* for the sake of simplicity only 16 bit pointers are supported */ + uint16_t TYPE; /* Unsigned 16 bit value. The resource record types - determines the content of the RDATA field. */ + uint16_t CLASS; /* Class of response. */ + uint32_t TTL; /* The time in seconds that the record may be cached. A value of 0 indicates the record should not be cached. */ + uint16_t RDLENGTH; /* Unsigned 16-bit value that defines the length in bytes of the RDATA record. */ + uint32_t RDATA; /* For the sake of simplicity only ipv4 is supported, and as such it's a unsigned 32 bit */ +} dns_answer_t; - -typedef struct __attribute__((__packed__)) dns_answer_t{ - uint16_t NAME; /* for the sake of simplicity only 16 bit pointers are supported */ - uint16_t TYPE; /* Unsigned 16 bit value. The resource record types - determines the content of the RDATA field. */ - uint16_t CLASS; /* Class of response. */ - uint32_t TTL; /* The time in seconds that the record may be cached. A value of 0 indicates the record should not be cached. */ - uint16_t RDLENGTH; /* Unsigned 16-bit value that defines the length in bytes of the RDATA record. */ - uint32_t RDATA; /* For the sake of simplicity only ipv4 is supported, and as such it's a unsigned 32 bit */ -}dns_answer_t; - -void dns_server(void *pvParameters); -void dns_server_start(esp_netif_t * netif); +void dns_server(void* pvParameters); +void dns_server_start(esp_netif_t* netif); void dns_server_stop(); - - #ifdef __cplusplus } #endif - #endif /* MAIN_DNS_SERVER_H_ */ diff --git a/components/wifi-manager/http_server_handlers.c b/components/wifi-manager/http_server_handlers.c index c776004a..417b2618 100644 --- a/components/wifi-manager/http_server_handlers.c +++ b/components/wifi-manager/http_server_handlers.c @@ -33,7 +33,6 @@ Copyright (c) 2017-2021 Sebastien L #include "tools_http_utils.h" #include "bootstate.h" - #define HTTP_STACK_SIZE (5 * 1024) const char str_na[] = "N/A"; #define STR_OR_NA(s) s ? s : str_na @@ -62,8 +61,7 @@ union sockaddr_aligned { esp_err_t post_handler_buff_receive(httpd_req_t* req); static const char redirect_payload1[] = "Redirecting to Captive " "Portal

Please wait, refreshing. If page does not refresh, click

Please wait, refreshing. If page does not refresh, click here to login.

"; /** @@ -82,12 +80,10 @@ char* alloc_get_http_header(httpd_req_t* req, const char* key) { /* Get header value string length and allocate memory for length + 1, * extra byte for null termination */ buf_len = httpd_req_get_hdr_value_len(req, key) + 1; - if (buf_len > 1) { + if(buf_len > 1) { buf = malloc_init_external(buf_len); /* Copy null terminated value string into buffer */ - if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) { - ESP_LOGD_LOC(TAG, "Found header => %s: %s", key, buf); - } + if(httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) { ESP_LOGD_LOC(TAG, "Found header => %s: %s", key, buf); } } return buf; } @@ -102,18 +98,18 @@ char* http_alloc_get_socket_address(httpd_req_t* req, u8_t local, in_port_t* por getaddrname_fn_t get_addr = NULL; int s = httpd_req_to_sockfd(req); - if (s == -1) { + if(s == -1) { free(ipstr); return strdup_psram("httpd_req_to_sockfd error"); } ESP_LOGV_LOC(TAG, "httpd socket descriptor: %u", s); get_addr = local ? &lwip_getsockname : &lwip_getpeername; - if (get_addr(s, (struct sockaddr*)&addr, &len) < 0) { + if(get_addr(s, (struct sockaddr*)&addr, &len) < 0) { ESP_LOGE_LOC(TAG, "Failed to retrieve socket address"); sprintf(ipstr, "N/A (0.0.0.%u)", local); } else { - if (addr.sin.sin_family == AF_INET6) { + if(addr.sin.sin_family == AF_INET6) { inet_ntop(AF_INET6, &addr.sin6.sin6_addr, ipstr, INET6_ADDRSTRLEN); ESP_LOGV_LOC(TAG, "Processing an IPV6 address : %s", ipstr); *portl = addr.sin6.sin6_port; @@ -134,7 +130,7 @@ bool is_captive_portal_host_name(httpd_req_t* req) { bool request_contains_hostname = false; esp_err_t hn_err = ESP_OK, err = ESP_OK; ESP_LOGD_LOC(TAG, "Getting adapter host name"); - if ((err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &host_name)) != ESP_OK) { + if((err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &host_name)) != ESP_OK) { ESP_LOGE_LOC(TAG, "Unable to get host name. Error: %s", esp_err_to_name(err)); } else { ESP_LOGD_LOC(TAG, "Host name is %s", host_name); @@ -143,18 +139,16 @@ bool is_captive_portal_host_name(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "Getting host name from request"); char* req_host = alloc_get_http_header(req, "Host"); - if (tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_AP)) { + if(tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_AP)) { ESP_LOGD_LOC(TAG, "Soft AP is enabled. getting ip info"); // Access point is up and running. Get the current IP address tcpip_adapter_ip_info_t ip_info; esp_err_t ap_ip_err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info); - if (ap_ip_err != ESP_OK) { - ESP_LOGE_LOC( - TAG, "Unable to get local AP ip address. Error: %s", esp_err_to_name(ap_ip_err)); + if(ap_ip_err != ESP_OK) { + ESP_LOGE_LOC(TAG, "Unable to get local AP ip address. Error: %s", esp_err_to_name(ap_ip_err)); } else { ESP_LOGD_LOC(TAG, "getting host name for TCPIP_ADAPTER_IF_AP"); - if ((hn_err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_AP, &ap_host_name)) != - ESP_OK) { + if((hn_err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_AP, &ap_host_name)) != ESP_OK) { ESP_LOGE_LOC(TAG, "Unable to get host name. Error: %s", esp_err_to_name(hn_err)); err = err == ESP_OK ? hn_err : err; } else { @@ -163,20 +157,17 @@ bool is_captive_portal_host_name(httpd_req_t* req) { ap_ip_address = malloc_init_external(IP4ADDR_STRLEN_MAX); memset(ap_ip_address, 0x00, IP4ADDR_STRLEN_MAX); - if (ap_ip_address) { + if(ap_ip_address) { ESP_LOGD_LOC(TAG, "Converting soft ip address to string"); esp_ip4addr_ntoa(&ip_info.ip, ap_ip_address, IP4ADDR_STRLEN_MAX); - ESP_LOGD_LOC( - TAG, "TCPIP_ADAPTER_IF_AP is up and has ip address %s ", ap_ip_address); + ESP_LOGD_LOC(TAG, "TCPIP_ADAPTER_IF_AP is up and has ip address %s ", ap_ip_address); } } } - if ((request_contains_hostname = (host_name != NULL) && (req_host != NULL) && - strcasestr(req_host, host_name)) == true) { + if((request_contains_hostname = (host_name != NULL) && (req_host != NULL) && strcasestr(req_host, host_name)) == true) { ESP_LOGD_LOC(TAG, "http request host = system host name %s", req_host); - } else if ((request_contains_hostname = (ap_host_name != NULL) && (req_host != NULL) && - strcasestr(req_host, ap_host_name)) == true) { + } else if((request_contains_hostname = (ap_host_name != NULL) && (req_host != NULL) && strcasestr(req_host, ap_host_name)) == true) { ESP_LOGD_LOC(TAG, "http request host = AP system host name %s", req_host); } @@ -189,7 +180,7 @@ bool is_captive_portal_host_name(httpd_req_t* req) { /* Custom function to free context */ void free_ctx_func(void* ctx) { session_context_t* context = (session_context_t*)ctx; - if (context) { + if(context) { ESP_LOGD(TAG, "Freeing up socket context"); FREE_AND_NULL(context->auth_token); FREE_AND_NULL(context->sess_ip_address); @@ -199,8 +190,8 @@ void free_ctx_func(void* ctx) { session_context_t* get_session_context(httpd_req_t* req) { bool newConnection = false; - ESP_LOGD_LOC(TAG,"Getting session context for %s",req->uri); - if (!req->sess_ctx) { + ESP_LOGD_LOC(TAG, "Getting session context for %s", req->uri); + if(!req->sess_ctx) { ESP_LOGD(TAG, "New connection context. Allocating session buffer"); req->sess_ctx = malloc_init_external(sizeof(session_context_t)); req->free_ctx = free_ctx_func; @@ -210,10 +201,7 @@ session_context_t* get_session_context(httpd_req_t* req) { session_context_t* ctx_data = (session_context_t*)req->sess_ctx; FREE_AND_NULL(ctx_data->sess_ip_address); ctx_data->sess_ip_address = http_alloc_get_socket_address(req, 0, &ctx_data->port); - if (newConnection) { - ESP_LOGI(TAG, "serving %s to peer %s port %u", req->uri, ctx_data->sess_ip_address, - ctx_data->port); - } + if(newConnection) { ESP_LOGI(TAG, "serving %s to peer %s port %u", req->uri, ctx_data->sess_ip_address, ctx_data->port); } return (session_context_t*)req->sess_ctx; } bool is_spiffs_safe_thread(httpd_req_t* req) { @@ -221,9 +209,9 @@ bool is_spiffs_safe_thread(httpd_req_t* req) { return ctx_data->signal != NULL; } void finalize_dispatch(httpd_req_t* req) { - ESP_LOGD_LOC(TAG,"Finalizing dispatch"); + ESP_LOGD_LOC(TAG, "Finalizing dispatch"); session_context_t* ctx_data = get_session_context(req); - if (!ctx_data) { + if(!ctx_data) { ESP_LOGE(TAG, "Invalid HTTP Context"); } else { xSemaphoreGive(ctx_data->signal); @@ -231,35 +219,30 @@ void finalize_dispatch(httpd_req_t* req) { } void dispatch_response(httpd_req_t* req, network_manager_ret_cb_t cb) { session_context_t* ctx_data = get_session_context(req); - if (!ctx_data) { + if(!ctx_data) { ESP_LOGE(TAG, "Invalid HTTP Context"); return; } ctx_data->signal = xSemaphoreCreateBinary(); - ESP_LOGD_LOC(TAG,"FIRING async task for %s",req->uri); + ESP_LOGD_LOC(TAG, "FIRING async task for %s", req->uri); network_async_callback_withret(req, cb); - ESP_LOGD_LOC(TAG,"WAITING for async task to complete for %s",req->uri); - if (xSemaphoreTake(ctx_data->signal, portMAX_DELAY) != pdTRUE) { - ESP_LOGE(TAG, "Async http failed for %s", req->uri); - } - ESP_LOGD_LOC(TAG,"COMPLETED Async task for %s",req->uri); + ESP_LOGD_LOC(TAG, "WAITING for async task to complete for %s", req->uri); + if(xSemaphoreTake(ctx_data->signal, portMAX_DELAY) != pdTRUE) { ESP_LOGE(TAG, "Async http failed for %s", req->uri); } + ESP_LOGD_LOC(TAG, "COMPLETED Async task for %s", req->uri); vSemaphoreDelete(ctx_data->signal); ctx_data->signal = NULL; } bool is_user_authenticated(httpd_req_t* req) { session_context_t* ctx_data = get_session_context(req); - if (ctx_data->authenticated) { + if(ctx_data->authenticated) { ESP_LOGD_LOC(TAG, "User is authenticated."); return true; } - ESP_LOGD(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_free_size(MALLOC_CAP_DMA), - heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); + ESP_LOGD(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), + heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_minimum_free_size(MALLOC_CAP_DMA)); // todo: ask for user to authenticate return false; @@ -272,15 +255,11 @@ static const char* get_path_from_uri(char* dest, const char* uri, size_t destsiz memset(dest, 0x0, destsize); const char* quest = strchr(uri, '?'); - if (quest) { - pathlen = MIN(pathlen, quest - uri); - } + if(quest) { pathlen = MIN(pathlen, quest - uri); } const char* hash = strchr(uri, '#'); - if (hash) { - pathlen = MIN(pathlen, hash - uri); - } + if(hash) { pathlen = MIN(pathlen, hash - uri); } - if (pathlen + 1 > destsize) { + if(pathlen + 1 > destsize) { /* Full path string won't fit into destination buffer */ return NULL; } @@ -289,16 +268,13 @@ static const char* get_path_from_uri(char* dest, const char* uri, size_t destsiz // strip trailing blanks char* sr = dest + pathlen; - while (*sr == ' ') - *sr-- = '\0'; + while(*sr == ' ') *sr-- = '\0'; char* last_fs = strchr(dest, '/'); - if (!last_fs) ESP_LOGD_LOC(TAG, "no / found in %s", dest); + if(!last_fs) ESP_LOGD_LOC(TAG, "no / found in %s", dest); char* p = last_fs; - while (p && *(++p) != '\0') { - if (*p == '/') { - last_fs = p; - } + while(p && *(++p) != '\0') { + if(*p == '/') { last_fs = p; } } /* Return pointer to path, skipping the base */ return last_fs ? ++last_fs : dest; @@ -307,9 +283,7 @@ bool hasFileExtension(const char* filename, const char* ext) { size_t fn_len = strlen(filename); size_t ext_len = strlen(ext); - if (ext_len > fn_len) { - return false; - } + if(ext_len > fn_len) { return false; } return strcasecmp(&filename[fn_len - ext_len], ext) == 0; } @@ -317,43 +291,43 @@ bool hasFileExtension(const char* filename, const char* ext) { static esp_err_t set_content_type_from_file(httpd_req_t* req, const char* full_name) { char filename[strlen(full_name) + 1]; strcpy(filename, full_name); - if (hasFileExtension(full_name, ".gz")) { + if(hasFileExtension(full_name, ".gz")) { httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); // Remove the .gz extension for MIME type detection filename[strlen(full_name) - 3] = '\0'; } - if (hasFileExtension(filename, ".html") || hasFileExtension(filename, ".htm")) { + if(hasFileExtension(filename, ".html") || hasFileExtension(filename, ".htm")) { return httpd_resp_set_type(req, "text/html"); - } else if (hasFileExtension(filename, ".css")) { + } else if(hasFileExtension(filename, ".css")) { return httpd_resp_set_type(req, "text/css"); - } else if (hasFileExtension(filename, ".js")) { + } else if(hasFileExtension(filename, ".js")) { return httpd_resp_set_type(req, "application/javascript"); - } else if (hasFileExtension(filename, ".json")) { + } else if(hasFileExtension(filename, ".json")) { return httpd_resp_set_type(req, "application/json"); - } else if (hasFileExtension(filename, ".xml")) { + } else if(hasFileExtension(filename, ".xml")) { return httpd_resp_set_type(req, "application/xml"); - } else if (hasFileExtension(filename, ".jpg") || hasFileExtension(filename, ".jpeg")) { + } else if(hasFileExtension(filename, ".jpg") || hasFileExtension(filename, ".jpeg")) { return httpd_resp_set_type(req, "image/jpeg"); - } else if (hasFileExtension(filename, ".png")) { + } else if(hasFileExtension(filename, ".png")) { return httpd_resp_set_type(req, "image/png"); - } else if (hasFileExtension(filename, ".gif")) { + } else if(hasFileExtension(filename, ".gif")) { return httpd_resp_set_type(req, "image/gif"); - } else if (hasFileExtension(filename, ".svg")) { + } else if(hasFileExtension(filename, ".svg")) { return httpd_resp_set_type(req, "image/svg+xml"); - } else if (hasFileExtension(filename, ".ico")) { + } else if(hasFileExtension(filename, ".ico")) { return httpd_resp_set_type(req, "image/x-icon"); - } else if (hasFileExtension(filename, ".pdf")) { + } else if(hasFileExtension(filename, ".pdf")) { return httpd_resp_set_type(req, "application/pdf"); - } else if (hasFileExtension(filename, ".txt")) { + } else if(hasFileExtension(filename, ".txt")) { return httpd_resp_set_type(req, "text/plain"); - } else if (hasFileExtension(filename, ".bin") || hasFileExtension(filename, ".dat")) { + } else if(hasFileExtension(filename, ".bin") || hasFileExtension(filename, ".dat")) { return httpd_resp_set_type(req, "application/octet-stream"); - } else if (hasFileExtension(filename, ".mp3")) { + } else if(hasFileExtension(filename, ".mp3")) { return httpd_resp_set_type(req, "audio/mpeg"); - } else if (hasFileExtension(filename, ".mp4")) { + } else if(hasFileExtension(filename, ".mp4")) { return httpd_resp_set_type(req, "video/mp4"); - } else if (hasFileExtension(filename, ".avi")) { + } else if(hasFileExtension(filename, ".avi")) { return httpd_resp_set_type(req, "video/x-msvideo"); } @@ -364,7 +338,7 @@ static esp_err_t set_content_type_from_file(httpd_req_t* req, const char* full_n static esp_err_t set_content_type_from_req(httpd_req_t* req) { char filepath[FILE_PATH_MAX]; const char* filename = get_path_from_uri(filepath, req->uri, sizeof(filepath)); - if (!filename) { + if(!filename) { ESP_LOGE_LOC(TAG, "Filename is too long"); /* Respond with 500 Internal Server Error */ httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long"); @@ -372,7 +346,7 @@ static esp_err_t set_content_type_from_req(httpd_req_t* req) { } /* If name has trailing '/', respond with directory contents */ - if (filename[strlen(filename) - 1] == '/' && strlen(filename) > 1) { + if(filename[strlen(filename) - 1] == '/' && strlen(filename) > 1) { httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Browsing files forbidden."); return ESP_FAIL; } @@ -413,13 +387,13 @@ static bool resolve_file_path(const char* uri, char* resolvedpath, size_t resolv snprintf(resolvedpath, resolvedsize, "%s%s", www_dir, uri); // Check if file exists - if (stat(resolvedpath, &file_stat) == 0) { + if(stat(resolvedpath, &file_stat) == 0) { // File exists return true; } else { // Check for compressed file strncat(resolvedpath, ".gz", resolvedsize - strlen(resolvedpath) - 1); - if (stat(resolvedpath, &file_stat) == 0) { + if(stat(resolvedpath, &file_stat) == 0) { // Compressed file exists return true; } @@ -430,7 +404,7 @@ static bool resolve_file_path(const char* uri, char* resolvedpath, size_t resolv } esp_err_t send_file_chunked(httpd_req_t* req, const char* filename) { struct stat file_stat = {}; - if (stat(filename, &file_stat) == -1) { + if(stat(filename, &file_stat) == -1) { ESP_LOGE(TAG, "Failed to stat file : %s", filename); /* Respond with 404 Not Found */ httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist"); @@ -438,7 +412,7 @@ esp_err_t send_file_chunked(httpd_req_t* req, const char* filename) { } FILE* fd = fopen(filename, "r"); - if (!fd) { + if(!fd) { ESP_LOGE(TAG, "Failed to read existing file : %s", filename); /* Respond with 500 Internal Server Error */ httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file"); @@ -453,56 +427,55 @@ esp_err_t send_file_chunked(httpd_req_t* req, const char* filename) { char* chunk = ((rest_server_context_t*)(req->user_ctx))->scratch; size_t chunksize; do { - ESP_LOGD_LOC(TAG,"More data to send"); + ESP_LOGD_LOC(TAG, "More data to send"); /* Read file in chunks into the scratch buffer */ chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd); - ESP_LOGD_LOC(TAG,"Read chunk size: %d",chunksize); - if (chunksize > 0) { + ESP_LOGD_LOC(TAG, "Read chunk size: %d", chunksize); + if(chunksize > 0) { /* Send the buffer contents as HTTP response chunk */ - if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) { + if(httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) { fclose(fd); ESP_LOGE(TAG, "File sending failed!"); /* Abort sending file */ - ESP_LOGD_LOC(TAG,"Sending NULL chunk"); + ESP_LOGD_LOC(TAG, "Sending NULL chunk"); httpd_resp_sendstr_chunk(req, NULL); - ESP_LOGD_LOC(TAG,"Sending 500 internal error"); + ESP_LOGD_LOC(TAG, "Sending 500 internal error"); /* Respond with 500 Internal Server Error */ httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file"); - ESP_LOGD_LOC(TAG,"returning"); + ESP_LOGD_LOC(TAG, "returning"); return ESP_FAIL; } } /* Keep looping till the whole file is sent */ - } while (chunksize != 0); + } while(chunksize != 0); /* Close file after sending complete */ fclose(fd); ESP_LOGI(TAG, "File sending complete for %s", req->uri); /* Respond with an empty chunk to signal HTTP response completion */ - ESP_LOGD_LOC(TAG,"Closing connection"); + ESP_LOGD_LOC(TAG, "Closing connection"); httpd_resp_send_chunk(req, NULL, 0); - return ESP_OK; } esp_err_t file_get_handler(httpd_req_t* req) { esp_err_t err = ESP_OK; char filepath[FILE_PATH_MAX]; - if (!is_spiffs_safe_thread(req)) { + if(!is_spiffs_safe_thread(req)) { dispatch_response(req, (network_manager_ret_cb_t)file_get_handler); return ESP_OK; } // const char* filename = get_path_from_uri(filepath, req->uri, sizeof(filepath)); ESP_LOGD_LOC(TAG, "Serving file from [%s]", req->uri); - if (err == ESP_OK && req->uri[strlen(req->uri) - 1] == '/') { + if(err == ESP_OK && req->uri[strlen(req->uri) - 1] == '/') { httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Browsing files forbidden."); err = ESP_FAIL; } - if (err == ESP_OK && strlen(req->uri) != 0 && hasFileExtension(req->uri, ".map")) { + if(err == ESP_OK && strlen(req->uri) != 0 && hasFileExtension(req->uri, ".map")) { err = httpd_resp_sendstr(req, ""); } else { - if (err == ESP_OK && !resolve_file_path(req->uri, filepath, sizeof(filepath))) { + if(err == ESP_OK && !resolve_file_path(req->uri, filepath, sizeof(filepath))) { httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); err = ESP_FAIL; } @@ -518,18 +491,18 @@ esp_err_t root_get_handler(httpd_req_t* req) { esp_err_t err = ESP_OK; ESP_LOGD(TAG, "Serving [%s]", req->uri); - if (!is_spiffs_safe_thread(req)) { + if(!is_spiffs_safe_thread(req)) { dispatch_response(req, (network_manager_ret_cb_t)root_get_handler); return ESP_OK; } - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // TODO: Send password entry page and return } httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_hdr(req, "Accept-Encoding", "identity"); - if (!resolve_file_path("/index.html", filepath, sizeof(filepath))) { + if(!resolve_file_path("/index.html", filepath, sizeof(filepath))) { httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); err = ESP_FAIL; } @@ -545,10 +518,9 @@ esp_err_t resource_filehandler(httpd_req_t* req) { return err; } - esp_err_t console_cmd_get_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } @@ -556,7 +528,7 @@ esp_err_t console_cmd_get_handler(httpd_req_t* req) { esp_err_t err = set_content_type_from_req(req); cJSON* cmdlist = get_cmd_list(); char* json_buffer = cJSON_Print(cmdlist); - if (json_buffer) { + if(json_buffer) { httpd_resp_send(req, (const char*)json_buffer, HTTPD_RESP_USE_STRLEN); free(json_buffer); } else { @@ -573,45 +545,38 @@ esp_err_t console_cmd_post_handler(httpd_req_t* req) { // bool bOTA=false; // char * otaURL=NULL; esp_err_t err = post_handler_buff_receive(req); - if (err != ESP_OK) { - return err; - } - if (!is_user_authenticated(req)) { + if(err != ESP_OK) { return err; } + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } char* command = ((rest_server_context_t*)(req->user_ctx))->scratch; cJSON* root = cJSON_Parse(command); - if (root == NULL) { + if(root == NULL) { ESP_LOGE_LOC(TAG, "Parsing command. Received content was: %s", command); - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed command json. Unable to parse content."); + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed command json. Unable to parse content."); return ESP_FAIL; } char* root_str = cJSON_Print(root); - if (root_str != NULL) { + if(root_str != NULL) { ESP_LOGD(TAG, "Processing command item: \n%s", root_str); free(root_str); } cJSON* item = cJSON_GetObjectItemCaseSensitive(root, "command"); - if (!item) { + if(!item) { ESP_LOGE_LOC(TAG, "Command not found. Received content was: %s", command); - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed command json. Unable to parse content."); + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed command json. Unable to parse content."); err = ESP_FAIL; } else { // navigate to the first child of the config structure char* cmd = cJSON_GetStringValue(item); - if (!console_push(cmd, strlen(cmd) + 1)) { - httpd_resp_send_err( - req, HTTPD_500_INTERNAL_SERVER_ERROR, "Unable to push command for execution"); + if(!console_push(cmd, strlen(cmd) + 1)) { + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Unable to push command for execution"); } else { httpd_resp_send(req, (const char*)success, strlen(success)); } @@ -628,15 +593,15 @@ esp_err_t post_handler_buff_receive(httpd_req_t* req) { int cur_len = 0; char* buf = ((rest_server_context_t*)(req->user_ctx))->scratch; int received = 0; - if (total_len >= SCRATCH_BUFSIZE) { + if(total_len >= SCRATCH_BUFSIZE) { /* Respond with 500 Internal Server Error */ ESP_LOGE_LOC(TAG, "Received content was too long. "); httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Content too long"); err = ESP_FAIL; } - while (err == ESP_OK && cur_len < total_len) { + while(err == ESP_OK && cur_len < total_len) { received = httpd_req_recv(req, buf + cur_len, total_len); - if (received <= 0) { + if(received <= 0) { /* Respond with 500 Internal Server Error */ ESP_LOGE_LOC(TAG, "Not all data was received. "); httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Not all data was received"); @@ -646,9 +611,7 @@ esp_err_t post_handler_buff_receive(httpd_req_t* req) { } } - if (err == ESP_OK) { - buf[total_len] = '\0'; - } + if(err == ESP_OK) { buf[total_len] = '\0'; } return err; } esp_err_t send_response(httpd_req_t* req, sys_request_response* response) { @@ -657,9 +620,7 @@ esp_err_t send_response(httpd_req_t* req, sys_request_response* response) { http_stream.callback = &out_http_binding; http_stream.state = req; http_stream.max_size = SIZE_MAX; - if (!pb_encode(&http_stream, &sys_request_response_msg, response)) { - err = ESP_FAIL; - } + if(!pb_encode(&http_stream, &sys_request_response_msg, response)) { err = ESP_FAIL; } /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_send_chunk(req, NULL, 0); return err; @@ -671,32 +632,28 @@ esp_err_t data_post_handler(httpd_req_t* req) { response.result = sys_request_result_SUCCESS; response.message = ""; char* otaURL = NULL; - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } pb_istream_t http_stream = PB_ISTREAM_EMPTY; http_stream.callback = &in_http_binding; http_stream.state = req; http_stream.bytes_left = req->content_len; - if (!pb_decode(&http_stream, &sys_request_payload_msg, &payload)) { + if(!pb_decode(&http_stream, &sys_request_payload_msg, &payload)) { httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, http_stream.errmsg); return ESP_FAIL; } ESP_LOGI(TAG, "Received Payload"); dump_structure(&sys_request_payload_msg, &payload); - switch (payload.type) { + switch(payload.type) { case sys_request_type_CONFIG: - if (payload.action == sys_request_action_GET) { - if (!config_http_send_config(req)) { - err = ESP_FAIL; - } + if(payload.action == sys_request_action_GET) { + if(!config_http_send_config(req)) { err = ESP_FAIL; } } else { // we are setting a config object httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Not implemented"); @@ -704,18 +661,15 @@ esp_err_t data_post_handler(httpd_req_t* req) { } break; case sys_request_type_STATUS: - if (payload.action == sys_request_action_GET) { - if(!network_status_send_object(req)){ - err = ESP_FAIL; - } - } - else { + if(payload.action == sys_request_action_GET) { + if(!network_status_send_object(req)) { err = ESP_FAIL; } + } else { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid request type"); err = ESP_FAIL; } - break; + break; case sys_request_type_SCAN: - if (payload.action == sys_request_action_GET) { + if(payload.action == sys_request_action_GET) { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "SCAN List should be retrieved with request type STATUS"); err = ESP_FAIL; } else { @@ -723,12 +677,12 @@ esp_err_t data_post_handler(httpd_req_t* req) { } break; case sys_request_type_OTA: - if (payload.which_data != sys_request_payload_URL_tag) { + if(payload.which_data != sys_request_payload_URL_tag) { response.result = sys_request_result_ERROR; response.message = "Missing URL"; } else { otaURL = strdup_psram(payload.data.URL); - if (is_recovery_running) { + if(is_recovery_running) { ESP_LOGW_LOC(TAG, "Starting process OTA for url %s", otaURL); } else { ESP_LOGW_LOC(TAG, "Restarting system to process OTA for url %s", otaURL); @@ -754,38 +708,28 @@ esp_err_t connect_post_handler(httpd_req_t* req) { char* host_name = NULL; esp_err_t err = post_handler_buff_receive(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } char* buf = ((rest_server_context_t*)(req->user_ctx))->scratch; - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } cJSON* root = cJSON_Parse(buf); - if (root == NULL) { + if(root == NULL) { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "JSON parsing error."); return ESP_FAIL; } cJSON* ssid_object = cJSON_GetObjectItem(root, "ssid"); - if (ssid_object != NULL) { - ssid = strdup_psram(ssid_object->valuestring); - } + if(ssid_object != NULL) { ssid = strdup_psram(ssid_object->valuestring); } cJSON* password_object = cJSON_GetObjectItem(root, "pwd"); - if (password_object != NULL) { - password = strdup_psram(password_object->valuestring); - } + if(password_object != NULL) { password = strdup_psram(password_object->valuestring); } cJSON* host_name_object = cJSON_GetObjectItem(root, "host_name"); - if (host_name_object != NULL) { - host_name = strdup_psram(host_name_object->valuestring); - } + if(host_name_object != NULL) { host_name = strdup_psram(host_name_object->valuestring); } cJSON_Delete(root); // if(host_name!=NULL){ @@ -795,13 +739,11 @@ esp_err_t connect_post_handler(httpd_req_t* req) { // } #pragma message("Update this to protocol buffers") - if (ssid != NULL && strlen(ssid) <= platform->net.max_ssid_size && - strlen(password) <= platform->net.max_password_size) { + if(ssid != NULL && strlen(ssid) <= platform->net.max_ssid_size && strlen(password) <= platform->net.max_password_size) { network_async_connect(ssid, password); httpd_resp_send(req, (const char*)success, strlen(success)); } else { - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Malformed json. Missing or invalid ssid/password."); + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Malformed json. Missing or invalid ssid/password."); err = ESP_FAIL; } // FREE_AND_NULL(ssid); @@ -813,14 +755,12 @@ esp_err_t connect_post_handler(httpd_req_t* req) { esp_err_t connect_delete_handler(httpd_req_t* req) { char success[] = "{}"; ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } httpd_resp_send(req, (const char*)success, strlen(success)); network_async_delete(); @@ -829,14 +769,12 @@ esp_err_t connect_delete_handler(httpd_req_t* req) { esp_err_t reboot_ota_post_handler(httpd_req_t* req) { char success[] = "{}"; ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } httpd_resp_send(req, (const char*)success, strlen(success)); network_async_reboot(OTA); @@ -845,14 +783,12 @@ esp_err_t reboot_ota_post_handler(httpd_req_t* req) { esp_err_t reboot_post_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); char success[] = "{}"; - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } httpd_resp_send(req, (const char*)success, strlen(success)); network_async_reboot(RESTART); return ESP_OK; @@ -860,14 +796,12 @@ esp_err_t reboot_post_handler(httpd_req_t* req) { esp_err_t recovery_post_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); char success[] = "{}"; - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } httpd_resp_send(req, (const char*)success, strlen(success)); network_async_reboot(RECOVERY); return ESP_OK; @@ -875,23 +809,20 @@ esp_err_t recovery_post_handler(httpd_req_t* req) { esp_err_t flash_post_handler(httpd_req_t* req) { esp_err_t err = ESP_OK; - if (is_recovery_running) { + if(is_recovery_running) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); char success[] = "File uploaded. Flashing started."; - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } err = httpd_resp_set_type(req, HTTPD_TYPE_TEXT); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } char* binary_buffer = malloc_init_external(req->content_len); - if (binary_buffer == NULL) { + if(binary_buffer == NULL) { ESP_LOGE(TAG, "File too large : %d bytes", req->content_len); /* Respond with 400 Bad Request */ - httpd_resp_send_err( - req, HTTPD_400_BAD_REQUEST, "Binary file too large. Unable to allocate memory!"); + httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Binary file too large. Unable to allocate memory!"); return ESP_FAIL; } ESP_LOGI(TAG, "Receiving ota binary file"); @@ -905,12 +836,12 @@ esp_err_t flash_post_handler(httpd_req_t* req) { * the size of the file being uploaded */ int remaining = req->content_len; - while (remaining > 0) { + while(remaining > 0) { ESP_LOGI(TAG, "Remaining size : %d", remaining); /* Receive the file part by part into a buffer */ - if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0) { - if (received == HTTPD_SOCK_ERR_TIMEOUT) { + if((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0) { + if(received == HTTPD_SOCK_ERR_TIMEOUT) { /* Retry if timeout occurred */ continue; } @@ -924,7 +855,7 @@ esp_err_t flash_post_handler(httpd_req_t* req) { } /* Write buffer content to file on storage */ - if (received) { + if(received) { memcpy(head, buf, received); head += received; } @@ -937,7 +868,7 @@ esp_err_t flash_post_handler(httpd_req_t* req) { /* Close file upon upload completion */ ESP_LOGI(TAG, "File reception complete. Invoking OTA process."); err = start_ota(NULL, binary_buffer, req->content_len); - if (err != ESP_OK) { + if(err != ESP_OK) { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "OTA processing failed"); goto bail_out; } @@ -958,11 +889,11 @@ char* get_ap_ip_address() { memset(ap_ip_address, 0x00, sizeof(ap_ip_address)); ESP_LOGD_LOC(TAG, "checking if soft AP is enabled"); - if (tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_AP)) { + if(tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_AP)) { ESP_LOGD_LOC(TAG, "Soft AP is enabled. getting ip info"); // Access point is up and running. Get the current IP address err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE_LOC(TAG, "Unable to get local AP ip address. Error: %s", esp_err_to_name(err)); } else { ESP_LOGV_LOC(TAG, "Converting soft ip address to string"); @@ -984,26 +915,23 @@ esp_err_t process_redirect(httpd_req_t* req, const char* status) { ESP_LOGD_LOC(TAG, "Getting remote socket address"); remote_ip = http_alloc_get_socket_address(req, 0, &port); - size_t buf_size = strlen(redirect_payload1) + strlen(redirect_payload2) + - strlen(redirect_payload3) + - 2 * (strlen(location_prefix) + strlen(ap_ip_address)) + 1; + size_t buf_size = + strlen(redirect_payload1) + strlen(redirect_payload2) + strlen(redirect_payload3) + 2 * (strlen(location_prefix) + strlen(ap_ip_address)) + 1; char* redirect = malloc_init_external(buf_size); - if (strcasestr(status, "302")) { + if(strcasestr(status, "302")) { size_t url_buf_size = strlen(location_prefix) + strlen(ap_ip_address) + 1; redirect_url = malloc_init_external(url_buf_size); memset(redirect_url, 0x00, url_buf_size); snprintf(redirect_url, buf_size, "%s%s/", location_prefix, ap_ip_address); - ESP_LOGW_LOC( - TAG, "Redirecting host [%s] to %s (from uri %s)", remote_ip, redirect_url, req->uri); + ESP_LOGW_LOC(TAG, "Redirecting host [%s] to %s (from uri %s)", remote_ip, redirect_url, req->uri); httpd_resp_set_hdr(req, "Location", redirect_url); snprintf(redirect, buf_size, "OK"); } else { - snprintf(redirect, buf_size, "%s%s%s%s%s%s%s", redirect_payload1, location_prefix, - ap_ip_address, redirect_payload2, location_prefix, ap_ip_address, redirect_payload3); - ESP_LOGW_LOC(TAG, "Responding to host [%s] (from uri %s) with redirect html page %s", - remote_ip, req->uri, redirect); + snprintf(redirect, buf_size, "%s%s%s%s%s%s%s", redirect_payload1, location_prefix, ap_ip_address, redirect_payload2, location_prefix, + ap_ip_address, redirect_payload3); + ESP_LOGW_LOC(TAG, "Responding to host [%s] (from uri %s) with redirect html page %s", remote_ip, req->uri, redirect); } httpd_resp_set_type(req, HTTPD_TYPE_TEXT); @@ -1048,14 +976,13 @@ esp_err_t redirect_processor(httpd_req_t* req, httpd_err_code_t error) { char* req_host = alloc_get_http_header(req, "Host"); user_agent = alloc_get_http_header(req, "User-Agent"); - if ((useragentiscaptivenetwork = - (user_agent != NULL && strcasestr(user_agent, "CaptiveNetworkSupport")) == true)) { + if((useragentiscaptivenetwork = (user_agent != NULL && strcasestr(user_agent, "CaptiveNetworkSupport")) == true)) { ESP_LOGW_LOC(TAG, "Found user agent that supports captive networks! [%s]", user_agent); } esp_err_t hn_err = ESP_OK; ESP_LOGV_LOC(TAG, "Getting adapter host name"); - if ((hn_err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &host_name)) != ESP_OK) { + if((hn_err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &host_name)) != ESP_OK) { ESP_LOGE_LOC(TAG, "Unable to get host name. Error: %s", esp_err_to_name(hn_err)); err = err == ESP_OK ? hn_err : err; } else { @@ -1069,45 +996,37 @@ esp_err_t redirect_processor(httpd_req_t* req, httpd_err_code_t error) { ESP_LOGD_LOC(TAG, "Peer IP: %s [port %u], System AP IP address: %s, System host: %s. Requested Host: [%s], " "uri [%s]", - STR_OR_NA(remote_ip), port, STR_OR_NA(ap_ip_address), STR_OR_NA(host_name), - STR_OR_NA(req_host), req->uri); + STR_OR_NA(remote_ip), port, STR_OR_NA(ap_ip_address), STR_OR_NA(host_name), STR_OR_NA(req_host), req->uri); /* captive portal functionality: redirect to access point IP for HOST that are not the access * point IP OR the STA IP */ /* determine if Host is from the STA IP address */ - if ((request_contains_hostname = (host_name != NULL) && (req_host != NULL) && - strcasestr(req_host, host_name)) == true) { + if((request_contains_hostname = (host_name != NULL) && (req_host != NULL) && strcasestr(req_host, host_name)) == true) { ESP_LOGD_LOC(TAG, "http request host = system host name %s", req_host); - } else if ((request_contains_hostname = (ap_host_name != NULL) && (req_host != NULL) && - strcasestr(req_host, ap_host_name)) == true) { + } else if((request_contains_hostname = (ap_host_name != NULL) && (req_host != NULL) && strcasestr(req_host, ap_host_name)) == true) { ESP_LOGD_LOC(TAG, "http request host = AP system host name %s", req_host); } - if ((request_contains_ap_ip_address = (ap_ip_address != NULL) && (req_host != NULL) && - strcasestr(req_host, ap_ip_address)) == true) { + if((request_contains_ap_ip_address = (ap_ip_address != NULL) && (req_host != NULL) && strcasestr(req_host, ap_ip_address)) == true) { ESP_LOGD_LOC(TAG, "http request host is access point ip address %s", req_host); } - if ((connected_to_ap_ip_interface = (ap_ip_address != NULL) && (socket_local_address != NULL) && - strcasestr(socket_local_address, ap_ip_address)) == true) { - ESP_LOGD_LOC( - TAG, "http request is connected to access point interface IP %s", ap_ip_address); + if((connected_to_ap_ip_interface = + (ap_ip_address != NULL) && (socket_local_address != NULL) && strcasestr(socket_local_address, ap_ip_address)) == true) { + ESP_LOGD_LOC(TAG, "http request is connected to access point interface IP %s", ap_ip_address); } - if ((request_is_sta_ip_address = (sta_ip_address != NULL) && (req_host != NULL) && - strcasestr(req_host, sta_ip_address)) == true) { + if((request_is_sta_ip_address = (sta_ip_address != NULL) && (req_host != NULL) && strcasestr(req_host, sta_ip_address)) == true) { ESP_LOGD_LOC(TAG, "http request host is WiFi client ip address %s", req_host); } - if ((connected_to_sta_ip_interface = - (sta_ip_address != NULL) && (socket_local_address != NULL) && - strcasestr(sta_ip_address, socket_local_address)) == true) { + if((connected_to_sta_ip_interface = + (sta_ip_address != NULL) && (socket_local_address != NULL) && strcasestr(sta_ip_address, socket_local_address)) == true) { ESP_LOGD_LOC(TAG, "http request is connected to WiFi client ip address %s", sta_ip_address); } - if ((error == 0) || (error == HTTPD_404_NOT_FOUND && connected_to_ap_ip_interface && - !(request_contains_ap_ip_address || request_contains_hostname))) { + if((error == 0) || + (error == HTTPD_404_NOT_FOUND && connected_to_ap_ip_interface && !(request_contains_ap_ip_address || request_contains_hostname))) { process_redirect(req, "302 Found"); } else { - ESP_LOGD_LOC( - TAG, "URL not found, and not processing captive portal so throw regular 404 error"); + ESP_LOGD_LOC(TAG, "URL not found, and not processing captive portal so throw regular 404 error"); httpd_resp_send_err(req, error, NULL); } @@ -1124,16 +1043,14 @@ esp_err_t redirect_ev_handler(httpd_req_t* req) { return redirect_processor(req, esp_err_t messages_get_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = set_content_type_from_req(req); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } cJSON* json_messages = messaging_retrieve_messages(messaging); - if (json_messages != NULL) { + if(json_messages != NULL) { char* json_text = cJSON_Print(json_messages); httpd_resp_send(req, (const char*)json_text, strlen(json_text)); free(json_text); @@ -1146,14 +1063,12 @@ esp_err_t messages_get_handler(httpd_req_t* req) { esp_err_t status_get_handler(httpd_req_t* req) { ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); - if (!is_user_authenticated(req)) { + if(!is_user_authenticated(req)) { // todo: redirect to login page // return ESP_OK; } esp_err_t err = httpd_resp_set_type(req, "application/octet-stream"); - if (err != ESP_OK) { - return err; - } + if(err != ESP_OK) { return err; } network_status_send_object(req); return ESP_OK; } @@ -1161,7 +1076,7 @@ esp_err_t status_get_handler(httpd_req_t* req) { esp_err_t err_handler(httpd_req_t* req, httpd_err_code_t error) { esp_err_t err = ESP_OK; - if (error != HTTPD_404_NOT_FOUND) { + if(error != HTTPD_404_NOT_FOUND) { err = httpd_resp_send_err(req, error, NULL); } else { err = redirect_processor(req, error); diff --git a/components/wifi-manager/http_server_handlers.h b/components/wifi-manager/http_server_handlers.h index d880c5a6..37799090 100644 --- a/components/wifi-manager/http_server_handlers.h +++ b/components/wifi-manager/http_server_handlers.h @@ -119,12 +119,12 @@ bool http_server_lock_json_object(TickType_t xTicksToWait); /* @brief unlock the json config object */ void http_server_unlock_json_object(); httpd_handle_t http_get_server(int* port); -#define PROTECTED_JSON_CALL(a) \ - if (http_server_lock_json_object(portMAX_DELAY)) { \ - \ a; \ - http_server_unlocklock_json_object(); \ - } else { \ - ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); \ +#define PROTECTED_JSON_CALL(a) \ + if(http_server_lock_json_object(portMAX_DELAY)) { \ + \ a; \ + http_server_unlocklock_json_object(); \ + } else { \ + ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); \ } #ifdef __cplusplus diff --git a/components/wifi-manager/network_driver_DM9051.c b/components/wifi-manager/network_driver_DM9051.c index 02905886..9b5bc8c3 100644 --- a/components/wifi-manager/network_driver_DM9051.c +++ b/components/wifi-manager/network_driver_DM9051.c @@ -6,10 +6,9 @@ static EXT_RAM_ATTR spi_device_interface_config_t devcfg; static EXT_RAM_ATTR esp_netif_config_t cfg_spi; static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config; static EXT_RAM_ATTR gpio_num_t rst = -1; -static esp_err_t reset_hw(esp_eth_phy_t *phy) -{ +static esp_err_t reset_hw(esp_eth_phy_t* phy) { // set reset_gpio_num to a negative value can skip hardware reset phy chip - if (rst >= 0) { + if(rst >= 0) { esp_rom_gpio_pad_select_gpio_x(rst); gpio_set_direction_x(rst, GPIO_MODE_OUTPUT); gpio_set_level_x(rst, 0); @@ -42,32 +41,29 @@ static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config* ether } static void init_config(sys_dev_eth_config* ethernet_config) { - esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); - devcfg.command_bits = 1; - devcfg.address_bits = 7; + esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + devcfg.command_bits = 1; + devcfg.address_bits = 7; devcfg.mode = 0; - devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed + devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed devcfg.queue_size = 20; devcfg.spics_io_num = ethernet_config->ethType.spi.cs; memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config)); - cfg_spi.base = &esp_netif_config, - cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; + cfg_spi.base = &esp_netif_config, cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; DM9051.cfg_netif = &cfg_spi; DM9051.devcfg = &devcfg; DM9051.start = start; } network_ethernet_driver_t* DM9051_Detect(sys_dev_eth_config* ethernet_config) { - if (ethernet_config->common.model != sys_dev_eth_models_DM9051 || - ethernet_config->which_ethType != sys_dev_eth_config_spi_tag ) - return NULL; + if(ethernet_config->common.model != sys_dev_eth_models_DM9051 || ethernet_config->which_ethType != sys_dev_eth_config_spi_tag) return NULL; DM9051.rmii = false; DM9051.spi = true; #ifdef CONFIG_ETH_SPI_ETHERNET_DM9051 DM9051.valid = true; #else DM9051.valid = false; -#endif +#endif DM9051.init_config = init_config; DM9051.model = ethernet_config->common.model; return &DM9051; diff --git a/components/wifi-manager/network_driver_LAN8720.c b/components/wifi-manager/network_driver_LAN8720.c index b607595e..33812639 100644 --- a/components/wifi-manager/network_driver_LAN8720.c +++ b/components/wifi-manager/network_driver_LAN8720.c @@ -6,10 +6,9 @@ static EXT_RAM_ATTR network_ethernet_driver_t LAN8720; static EXT_RAM_ATTR esp_netif_config_t cfg_rmii; static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config; static EXT_RAM_ATTR gpio_num_t rst = -1; -static esp_err_t reset_hw(esp_eth_phy_t *phy) -{ +static esp_err_t reset_hw(esp_eth_phy_t* phy) { // set reset_gpio_num to a negative value can skip hardware reset phy chip - if (rst >= 0) { + if(rst >= 0) { esp_rom_gpio_pad_select_gpio_x(rst); gpio_set_direction_x(rst, GPIO_MODE_OUTPUT); gpio_set_level_x(rst, 0); @@ -19,7 +18,7 @@ static esp_err_t reset_hw(esp_eth_phy_t *phy) } return ESP_OK; } -static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethernet_config) { +static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config* ethernet_config) { #ifdef CONFIG_ETH_PHY_INTERFACE_RMII eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); @@ -42,26 +41,23 @@ static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethe #endif } -static void init_config(sys_dev_eth_config * ethernet_config) { - esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); +static void init_config(sys_dev_eth_config* ethernet_config) { + esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config)); - - cfg_rmii.base = &esp_netif_config, - cfg_rmii.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; - + + cfg_rmii.base = &esp_netif_config, cfg_rmii.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; + LAN8720.cfg_netif = &cfg_rmii; LAN8720.start = start; } -network_ethernet_driver_t* LAN8720_Detect(sys_dev_eth_config * ethernet_config) { - if (ethernet_config->common.model != sys_dev_eth_models_LAN8720 || - ethernet_config->which_ethType != sys_dev_eth_config_rmii_tag) - return NULL; +network_ethernet_driver_t* LAN8720_Detect(sys_dev_eth_config* ethernet_config) { + if(ethernet_config->common.model != sys_dev_eth_models_LAN8720 || ethernet_config->which_ethType != sys_dev_eth_config_rmii_tag) return NULL; #ifdef CONFIG_ETH_PHY_INTERFACE_RMII LAN8720.valid = true; #else LAN8720.valid = false; -#endif +#endif LAN8720.rmii = true; LAN8720.spi = false; LAN8720.model = ethernet_config->common.model; diff --git a/components/wifi-manager/network_driver_W5500.c b/components/wifi-manager/network_driver_W5500.c index 6fd14d0f..78f38159 100644 --- a/components/wifi-manager/network_driver_W5500.c +++ b/components/wifi-manager/network_driver_W5500.c @@ -6,10 +6,9 @@ static EXT_RAM_ATTR spi_device_interface_config_t devcfg; static EXT_RAM_ATTR esp_netif_config_t cfg_spi; static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config; static EXT_RAM_ATTR gpio_num_t rst = -1; -static esp_err_t reset_hw(esp_eth_phy_t *phy) -{ +static esp_err_t reset_hw(esp_eth_phy_t* phy) { // set reset_gpio_num to a negative value can skip hardware reset phy chip - if (rst >= 0) { + if(rst >= 0) { esp_rom_gpio_pad_select_gpio_x(rst); gpio_set_direction_x(rst, GPIO_MODE_OUTPUT); gpio_set_level_x(rst, 0); @@ -19,7 +18,7 @@ static esp_err_t reset_hw(esp_eth_phy_t *phy) return ESP_OK; } -static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethernet_config) { +static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config* ethernet_config) { #ifdef CONFIG_ETH_SPI_ETHERNET_W5500 spi_host_device_t spi_host = ethernet_config->ethType.spi.host - sys_dev_common_hosts_Host0; eth_w5500_config_t eth_config = ETH_W5500_DEFAULT_CONFIG(spi_host, &devcfg); @@ -28,7 +27,7 @@ static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethe (void)spi_handle; eth_config.int_gpio_num = ethernet_config->ethType.spi.intr; - phy_config.phy_addr = -1; // let the system automatically find out the phy address + phy_config.phy_addr = -1; // let the system automatically find out the phy address rst = ethernet_config->common.rst; phy_config.reset_gpio_num = rst; @@ -41,30 +40,26 @@ static esp_err_t start(spi_device_handle_t spi_handle, sys_dev_eth_config * ethe return ESP_ERR_NOT_SUPPORTED; #endif } -static void init_config(sys_dev_eth_config * ethernet_config) { +static void init_config(sys_dev_eth_config* ethernet_config) { // This function is called when the network interface is started - // and performs any initialization that requires a valid ethernet + // and performs any initialization that requires a valid ethernet // configuration . esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); - devcfg.command_bits = 16; // Actually it's the address phase in W5500 SPI frame - devcfg.address_bits = 8; // Actually it's the control phase in W5500 SPI frame + devcfg.command_bits = 16; // Actually it's the address phase in W5500 SPI frame + devcfg.address_bits = 8; // Actually it's the control phase in W5500 SPI frame devcfg.mode = 0; - devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed + devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed devcfg.queue_size = 20; - devcfg.spics_io_num = ethernet_config->ethType.spi.cs; + devcfg.spics_io_num = ethernet_config->ethType.spi.cs; memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config)); - cfg_spi.base = &esp_netif_config, - cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; + cfg_spi.base = &esp_netif_config, cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; W5500.cfg_netif = &cfg_spi; W5500.devcfg = &devcfg; W5500.start = start; - } -network_ethernet_driver_t* W5500_Detect(sys_dev_eth_config * ethernet_config) { - if (ethernet_config->common.model != sys_dev_eth_models_W5500 || - ethernet_config->which_ethType != sys_dev_eth_config_spi_tag ) - return NULL; - W5500.init_config = init_config; +network_ethernet_driver_t* W5500_Detect(sys_dev_eth_config* ethernet_config) { + if(ethernet_config->common.model != sys_dev_eth_models_W5500 || ethernet_config->which_ethType != sys_dev_eth_config_spi_tag) return NULL; + W5500.init_config = init_config; W5500.spi = true; W5500.rmii = false; W5500.model = ethernet_config->common.model; @@ -72,6 +67,6 @@ network_ethernet_driver_t* W5500_Detect(sys_dev_eth_config * ethernet_config) { W5500.valid = true; #else W5500.valid = false; -#endif +#endif return &W5500; } diff --git a/components/wifi-manager/network_ethernet.c b/components/wifi-manager/network_ethernet.c index b961a8c1..76432471 100644 --- a/components/wifi-manager/network_ethernet.c +++ b/components/wifi-manager/network_ethernet.c @@ -24,16 +24,16 @@ static network_ethernet_detect_func_t* drivers[] = {DM9051_Detect, W5500_Detect, #define ETH_TIMEOUT_MS (30 * 1000) network_ethernet_driver_t* network_ethernet_driver_autodetect() { - sys_dev_eth_config * eth_config; + sys_dev_eth_config* eth_config; sys_dev_eth_common* eth_common; - if (!SYS_ETH(eth_config) || !SYS_ETH_COMMON(eth_common)) { + if(!SYS_ETH(eth_config) || !SYS_ETH_COMMON(eth_common)) { ESP_LOGD(TAG, "Ethernet not configured"); return NULL; } - for (uint8_t i = _sys_dev_eth_models_MIN; i < _sys_dev_eth_models_MAX; i++) { + for(uint8_t i = _sys_dev_eth_models_MIN; i < _sys_dev_eth_models_MAX; i++) { network_ethernet_driver_t* found_driver = drivers[i](eth_config); - if (found_driver) { + if(found_driver) { ESP_LOGI(TAG, "Detected driver %s ", sys_dev_eth_models_name(eth_common->model)); network_driver = found_driver; return found_driver; @@ -48,12 +48,12 @@ esp_netif_t* network_ethernet_get_interface() { return eth_netif; } bool network_ethernet_is_up() { return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0; } bool network_ethernet_enabled() { return network_driver != NULL && network_driver->handle != NULL; } bool network_ethernet_wait_for_link(uint16_t max_wait_ms) { - if (!network_ethernet_enabled()) return false; + if(!network_ethernet_enabled()) return false; bool link_up = (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0; - if (!link_up) { + if(!link_up) { ESP_LOGD(TAG, "Waiting for Ethernet link to be established..."); link_up = (xEventGroupWaitBits(ethernet_event_group, LINK_UP_BIT, pdFALSE, pdTRUE, max_wait_ms / portTICK_PERIOD_MS) & LINK_UP_BIT) != 0; - if (!link_up) { + if(!link_up) { ESP_LOGW(TAG, "Ethernet Link timeout."); } else { ESP_LOGI(TAG, "Ethernet Link Up!"); @@ -66,21 +66,21 @@ static void ETH_Timeout(TimerHandle_t timer); void destroy_network_ethernet() {} static void network_ethernet_print_config(const network_ethernet_driver_t* eth_config) { - sys_dev_eth_config * sys_eth; + sys_dev_eth_config* sys_eth; int mdc = -1, mdio = -1, rst = -1, intr = -1, cs = -1; uint32_t speed = 0; int8_t host = 0; - if (SYS_ETH(sys_eth)) { + if(SYS_ETH(sys_eth)) { rst = sys_eth->common.rst; - if (sys_eth->which_ethType == sys_dev_eth_config_spi_tag) { + if(sys_eth->which_ethType == sys_dev_eth_config_spi_tag) { cs = sys_eth->ethType.spi.cs; intr = sys_eth->ethType.spi.intr; speed = sys_eth->ethType.spi.speed; host = sys_eth->ethType.spi.host - sys_dev_common_hosts_Host0; - } else if (sys_eth->which_ethType == sys_dev_eth_config_rmii_tag) { + } else if(sys_eth->which_ethType == sys_dev_eth_config_rmii_tag) { mdc = sys_eth->ethType.rmii.mdc; mdio = sys_eth->ethType.rmii.mdio; } @@ -88,20 +88,20 @@ static void network_ethernet_print_config(const network_ethernet_driver_t* eth_c ESP_LOGI(TAG, "Ethernet config => model: %s, valid: %s, type: %s, mdc:%d, mdio:%d, rst:%d, intr:%d, " "cs:%d, speed:%d, host:%d", - sys_dev_eth_models_name(eth_config->model), eth_config->valid ? "YES" : "NO", eth_config->spi ? "SPI" : "RMII", mdc, mdio, rst, intr, cs, speed, - host); + sys_dev_eth_models_name(eth_config->model), eth_config->valid ? "YES" : "NO", eth_config->spi ? "SPI" : "RMII", mdc, mdio, rst, intr, cs, + speed, host); } void init_network_ethernet() { esp_err_t err = ESP_OK; ESP_LOGI(TAG, "Attempting to initialize Ethernet"); - sys_dev_eth_config * sys_eth; - if (!SYS_ETH(sys_eth)) { + sys_dev_eth_config* sys_eth; + if(!SYS_ETH(sys_eth)) { ESP_LOGD(TAG, "No ethernet configured"); return; } network_ethernet_driver_t* driver = network_ethernet_driver_autodetect(); - if (!driver || !driver->valid) { + if(!driver || !driver->valid) { ESP_LOGI(TAG, "No Ethernet configuration, or configuration invalid"); return; } @@ -115,7 +115,7 @@ void init_network_ethernet() { ethernet_event_group = xEventGroupCreate(); xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT); err = network_driver->start(NULL, sys_eth); - if (err == ESP_OK) { + if(err == ESP_OK) { uint8_t mac_address[6]; esp_read_mac(mac_address, ESP_MAC_ETH); char* mac_string = alloc_get_formatted_mac_string(mac_address); @@ -123,15 +123,15 @@ void init_network_ethernet() { FREE_AND_NULL(mac_string); esp_eth_ioctl(network_driver->handle, ETH_CMD_S_MAC_ADDR, mac_address); } - if (err == ESP_OK) { + if(err == ESP_OK) { ESP_LOGD(TAG, "Attaching ethernet to network interface"); err = esp_netif_attach(eth_netif, esp_eth_new_netif_glue(network_driver->handle)); } - if (err == ESP_OK) { + if(err == ESP_OK) { ESP_LOGI(TAG, "Starting ethernet network"); err = esp_eth_start(network_driver->handle); } - if (err != ESP_OK) { + if(err != ESP_OK) { messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Configuring Ethernet failed: %s", esp_err_to_name(err)); network_driver->handle = NULL; } @@ -143,9 +143,9 @@ void network_ethernet_start_timer() { ETH_timer = xTimerCreate("ETH check", pdMS static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { uint8_t mac_addr[6] = {0}; /* we can get the ethernet driver handle from event data */ - if (event_base == ETH_EVENT) { + if(event_base == ETH_EVENT) { esp_eth_handle_t eth_handle = *(esp_eth_handle_t*)event_data; - switch (event_id) { + switch(event_id) { case ETHERNET_EVENT_CONNECTED: xEventGroupSetBits(ethernet_event_group, LINK_UP_BIT); esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); diff --git a/components/wifi-manager/network_ethernet.h b/components/wifi-manager/network_ethernet.h index 0aae961e..2bc5eee9 100644 --- a/components/wifi-manager/network_ethernet.h +++ b/components/wifi-manager/network_ethernet.h @@ -39,15 +39,15 @@ typedef struct { bool spi; sys_dev_eth_models model; esp_eth_handle_t handle; - esp_netif_config_t * cfg_netif; - spi_device_interface_config_t * devcfg; + esp_netif_config_t* cfg_netif; + spi_device_interface_config_t* devcfg; // This function is called when the network interface is started - // and performs any initialization that requires a valid ethernet + // and performs any initialization that requires a valid ethernet // configuration . - void (*init_config)(sys_dev_eth_config * config); - esp_err_t (*start)(spi_device_handle_t spi_handle,sys_dev_eth_config * config); + void (*init_config)(sys_dev_eth_config* config); + esp_err_t (*start)(spi_device_handle_t spi_handle, sys_dev_eth_config* config); } network_ethernet_driver_t; -typedef network_ethernet_driver_t* network_ethernet_detect_func_t(sys_dev_eth_config * config); +typedef network_ethernet_driver_t* network_ethernet_detect_func_t(sys_dev_eth_config* config); network_ethernet_driver_t* network_ethernet_driver_autodetect(); void destroy_network_ethernet(); void init_network_ethernet(); @@ -56,7 +56,7 @@ bool network_ethernet_wait_for_link(uint16_t max_wait_ms); void network_ethernet_start_timer(); bool network_ethernet_is_up(); bool network_ethernet_enabled(); -esp_netif_t *network_ethernet_get_interface(); +esp_netif_t* network_ethernet_get_interface(); #ifdef __cplusplus } diff --git a/components/wifi-manager/network_manager.c b/components/wifi-manager/network_manager.c index 4e2e5d59..3921e499 100644 --- a/components/wifi-manager/network_manager.c +++ b/components/wifi-manager/network_manager.c @@ -79,50 +79,42 @@ void network_start_stop_dhcp_client(esp_netif_t* netif, bool start) { tcpip_adapter_dhcp_status_t status; esp_err_t err = ESP_OK; ESP_LOGD(TAG, "Checking if DHCP client for STA interface is running"); - if (!netif) { + if(!netif) { ESP_LOGE(TAG, "Invalid adapter. Cannot start/stop dhcp. "); return; } - if ((err = esp_netif_dhcpc_get_status(netif, &status)) != ESP_OK) { + if((err = esp_netif_dhcpc_get_status(netif, &status)) != ESP_OK) { ESP_LOGE(TAG, "Error retrieving dhcp status : %s", esp_err_to_name(err)); return; } - switch (status) { + switch(status) { case ESP_NETIF_DHCP_STARTED: - if (start) { + if(start) { ESP_LOGD(TAG, "DHCP client already started"); } else { ESP_LOGI(TAG, "Stopping DHCP client"); err = esp_netif_dhcpc_stop(netif); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } } break; case ESP_NETIF_DHCP_STOPPED: - if (start) { + if(start) { ESP_LOGI(TAG, "ESP_NETIF_DHCP_STOPPED Starting DHCP client"); err = esp_netif_dhcpc_start(netif); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } } else { ESP_LOGI(TAG, "DHCP client already started"); } break; case ESP_NETIF_DHCP_INIT: - if (start) { + if(start) { ESP_LOGI(TAG, "ESP_NETIF_DHCP_INIT: Starting DHCP client"); err = esp_netif_dhcpc_start(netif); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } } else { ESP_LOGI(TAG, "Stopping DHCP client"); err = esp_netif_dhcpc_stop(netif); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { ESP_LOGE(TAG, "Error stopping DHCP Client : %s", esp_err_to_name(err)); } } break; @@ -135,17 +127,17 @@ void network_start_stop_dhcps(esp_netif_t* netif, bool start) { tcpip_adapter_dhcp_status_t status; esp_err_t err = ESP_OK; ESP_LOGD(TAG, "Checking if DHCP server is running"); - if (!netif) { + if(!netif) { ESP_LOGE(TAG, "Invalid adapter. Cannot start/stop dhcp server. "); return; } - if ((err = esp_netif_dhcps_get_status(netif, &status)) != ESP_OK) { + if((err = esp_netif_dhcps_get_status(netif, &status)) != ESP_OK) { ESP_LOGE(TAG, "Error retrieving dhcp server status : %s", esp_err_to_name(err)); return; } - switch (status) { + switch(status) { case ESP_NETIF_DHCP_STARTED: - if (start) { + if(start) { ESP_LOGD(TAG, "DHCP server already started"); } else { ESP_LOGI(TAG, "Stopping DHCP server"); @@ -153,7 +145,7 @@ void network_start_stop_dhcps(esp_netif_t* netif, bool start) { } break; case ESP_NETIF_DHCP_STOPPED: - if (start) { + if(start) { ESP_LOGI(TAG, "Starting DHCP server"); ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif)); } else { @@ -161,7 +153,7 @@ void network_start_stop_dhcps(esp_netif_t* netif, bool start) { } break; case ESP_NETIF_DHCP_INIT: - if (start) { + if(start) { ESP_LOGI(TAG, "Starting DHCP server"); ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif)); } else { @@ -185,10 +177,8 @@ void network_start_stop_dhcps(esp_netif_t* netif, bool start) { #define ADD_EVENT(name) CASE_TO_STR(name); #define ADD_FIRST_EVENT(name) CASE_TO_STR(name); static const char* state_to_string(const state_t* state) { - if (!state) { - return ""; - } - switch (state->Parent ? state->Parent->Id : state->Id) { + if(!state) { return ""; } + switch(state->Parent ? state->Parent->Id : state->Id) { ALL_NM_STATE default: break; @@ -196,7 +186,7 @@ static const char* state_to_string(const state_t* state) { return "Unknown"; } static const char* wifi_state_to_string(mn_wifi_active_state_t state) { - switch (state) { + switch(state) { ALL_WIFI_STATE(, ) default: break; @@ -204,7 +194,7 @@ static const char* wifi_state_to_string(mn_wifi_active_state_t state) { return "Unknown"; } static const char* eth_state_to_string(mn_eth_active_state_t state) { - switch (state) { + switch(state) { ALL_ETH_STATE(, ) default: break; @@ -212,7 +202,7 @@ static const char* eth_state_to_string(mn_eth_active_state_t state) { return "Unknown"; } static const char* wifi_configuring_state_to_string(mn_wifi_configuring_state_t state) { - switch (state) { + switch(state) { ALL_WIFI_CONFIGURING_STATE(, ) default: break; @@ -220,11 +210,9 @@ static const char* wifi_configuring_state_to_string(mn_wifi_configuring_state_t return "Unknown"; } static const char* sub_state_to_string(const state_t* state) { - if (!state) { - return "N/A"; - } + if(!state) { return "N/A"; } int root_id = get_root_id(state); - switch (root_id) { + switch(root_id) { case NETWORK_ETH_ACTIVE_STATE: return eth_state_to_string(state->Id); break; @@ -239,7 +227,7 @@ static const char* sub_state_to_string(const state_t* state) { } const char* network_event_to_string(network_event_t state) { - switch (state) { + switch(state) { ALL_NM_EVENTS default: @@ -265,27 +253,26 @@ static const max_sub_states_t state_max[] = {{.parent_state = NETWORK_INSTANTIAT {.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE - 1}, {.parent_state = -1}}; void check_queue() { - if (!network_queue) { + if(!network_queue) { ESP_LOGD(TAG, " Creating message queue"); network_queue = xQueueCreate(6, sizeof(queue_message)); } } void network_initialize_task() { - if (cold_boot) { + if(cold_boot) { ESP_LOGI(TAG, "Setting wifi priotitized flag to false"); s_wifi_prioritized = false; } check_queue(); ESP_LOGD(TAG, "Creating network manager task"); network_task_handle = xTaskCreate(&network_task, "network", 4096 * 2, NULL, ESP_TASK_TIMER_PRIO, &task_network_manager); - } static void event_logger(uint32_t state_machine, uint32_t state, uint32_t event) { ESP_LOGD(TAG, "Handling network manager event state Id %d->[%s]", state, network_event_to_string(event)); } static const char* get_state_machine_result_string(state_machine_result_t result) { - switch (result) { + switch(result) { case EVENT_HANDLED: return "EVENT_HANDLED"; case EVENT_UN_HANDLED: @@ -309,41 +296,35 @@ static void network_task(void* pvParameters) { // else, as some critical initialization happen there. network_async_front(EN_START); /* main processing loop */ - for (;;) { + for(;;) { xStatus = xQueueReceive(network_queue, &msg, portMAX_DELAY); - if (xStatus == pdPASS) { + if(xStatus == pdPASS) { // pass the event to the sync processor NM.event_parameters = &msg; NM.Machine.Event = msg.trigger; - if (dispatch_event(SM, 1, event_logger, result_logger) == EVENT_UN_HANDLED) { + if(dispatch_event(SM, 1, event_logger, result_logger) == EVENT_UN_HANDLED) { network_manager_format_from_to_states( ESP_LOG_ERROR, "Unhandled Event", NULL, NM.Machine.State, msg.trigger, false, "network manager"); } } /* end of if status=pdPASS */ - } /* end of for loop */ + } /* end of for loop */ vTaskDelete(NULL); } int get_max_substate(nm_state_t state) { - for (int i = 0; state_max[i].parent_state != -1; i++) { - if (state_max[i].parent_state == state) { - return state_max[i].sub_state_last; - } + for(int i = 0; state_max[i].parent_state != -1; i++) { + if(state_max[i].parent_state == state) { return state_max[i].sub_state_last; } } return -1; } esp_err_t network_register_state_callback(nm_state_t state, int sub_state, const char* from, network_status_reached_cb cb) { network_callback_t* item = NULL; - if (!cb) { - return ESP_ERR_INVALID_ARG; - } + if(!cb) { return ESP_ERR_INVALID_ARG; } item = calloc(1, sizeof(*item)); - if (item == NULL) { - return ESP_ERR_NO_MEM; - } - if (sub_state != -1 && sub_state > get_max_substate(state)) { + if(item == NULL) { return ESP_ERR_NO_MEM; } + if(sub_state != -1 && sub_state > get_max_substate(state)) { // sub state has to be valid return ESP_ERR_INVALID_ARG; } @@ -353,23 +334,21 @@ esp_err_t network_register_state_callback(nm_state_t state, int sub_state, const item->from = from; item->sub_state = sub_state; network_callback_t* last = SLIST_FIRST(&s_cb_list); - if (last == NULL) { + if(last == NULL) { SLIST_INSERT_HEAD(&s_cb_list, item, next); } else { network_callback_t* it; - while ((it = SLIST_NEXT(last, next)) != NULL) { - last = it; - } + while((it = SLIST_NEXT(last, next)) != NULL) { last = it; } SLIST_INSERT_AFTER(last, item, next); } return ESP_OK; } const state_t* get_root(const state_t* const state) { - if (!state) return NULL; + if(!state) return NULL; return state->Parent == NULL ? state : get_root(state->Parent); } int get_root_id(const state_t* state) { - if (!state) return -1; + if(!state) return -1; return state->Parent == NULL ? state->Id : get_root_id(state->Parent); } @@ -381,7 +360,7 @@ static bool is_current_state(const state_t* state, nm_state_t state_id, int sub_ void network_execute_cb(state_machine_t* const state_machine, const char* caller) { network_callback_t* it; SLIST_FOREACH(it, &s_cb_list, next) { - if (is_current_state(state_machine->State, it->state, it->sub_state)) { + if(is_current_state(state_machine->State, it->state, it->sub_state)) { char* cb_prefix = messaging_alloc_format_string("BEGIN Executing Callback %s", it->from); NETWORK_DEBUG_STATE_MACHINE(true, STR_OR_BLANK(cb_prefix), state_machine, false, STR_OR_BLANK(caller)); FREE_AND_NULL(cb_prefix); @@ -397,7 +376,7 @@ bool network_is_wifi_prioritized() { sys_dev_eth_common* common = NULL; bool result = s_wifi_prioritized; bool valid_model = SYS_ETH_COMMON(common) && common->model != sys_dev_eth_models_NONE; - if (result) { + if(result) { result = network_wifi_get_known_count() > 0 || !valid_model; ESP_LOGD(TAG, "Wifi is prioritized with %d known access points.%s %s", network_wifi_get_known_count(), valid_model ? " And a valid ethernet adapter" : "", result ? "Wifi prioritized" : "Ethernet prioritized"); @@ -406,7 +385,7 @@ bool network_is_wifi_prioritized() { } void network_prioritize_wifi(bool activate) { - if (s_wifi_prioritized == activate) return; + if(s_wifi_prioritized == activate) return; s_wifi_prioritized = activate; ESP_LOGI(TAG, "Wifi is %sprioritized", activate ? "" : "not "); } @@ -417,7 +396,7 @@ void network_manager_format_state_machine( state_t const* current_state = NULL; network_event_t event = -1; - if (state_machine) { + if(state_machine) { source_state = ((network_t*)state_machine)->source_state; current_state = state_machine->State; event = state_machine->Event; @@ -433,17 +412,17 @@ void network_manager_format_from_to_states(esp_log_level_t level, const char* pr const char* state = "N/A"; const char* sub_state = "N/A"; - if (current_state) { + if(current_state) { state = state_to_string(current_state); sub_state = sub_state_to_string(current_state); } - if (!from_state) { + if(!from_state) { source_state = "N/A"; } else { source_state = state_to_string(from_state); source_sub_state = sub_state_to_string(from_state); } - if (show_source) { + if(show_source) { ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s)->%s(%s) [%s]", STR_OR_BLANK(caller), prefix, source_state, source_sub_state, state, sub_state, network_event_to_string(event)); } else { @@ -453,9 +432,9 @@ void network_manager_format_from_to_states(esp_log_level_t level, const char* pr #define xSafeQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait) \ check_queue(); \ xQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait); -#define xSafeQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait) \ +#define xSafeQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait) \ check_queue(); \ - xQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait); + xQueueSendToFront(xQueue, pvItemToQueue, xTicksToWait); void network_async(network_event_t trigger) { queue_message msg; memset(&msg, 0x00, sizeof(msg)); @@ -463,11 +442,11 @@ void network_async(network_event_t trigger) { ESP_LOGD(TAG, "Posting event %s directly", network_event_to_string(trigger)); xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } -void network_async_got_ip(network_event_t trigger,ip_event_got_ip_t*event_data) { +void network_async_got_ip(network_event_t trigger, ip_event_got_ip_t* event_data) { queue_message msg; memset(&msg, 0x00, sizeof(msg)); msg.trigger = trigger; - msg.ctx.got_ip_event_data = (ip_event_got_ip_t*)clone_obj_psram(event_data,sizeof(ip_event_got_ip_t)); + msg.ctx.got_ip_event_data = (ip_event_got_ip_t*)clone_obj_psram(event_data, sizeof(ip_event_got_ip_t)); ESP_LOGD(TAG, "Posting event %s", network_event_to_string(trigger)); xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } @@ -503,12 +482,12 @@ void network_async_update_status() { network_async(EN_UPDATE_STATUS); } void network_async_delete() { network_async(EN_DELETE); } void network_async_scan_done() { network_async(EN_SCAN_DONE); } -void network_async_delete_connection(const char * ssid){ +void network_async_delete_connection(const char* ssid) { queue_message msg; memset(&msg, 0x00, sizeof(msg)); msg.trigger = EN_REMOVE; msg.ctx.credentials.ssid = strdup_psram(ssid); - ESP_LOGD(TAG, "Posting event %s for ssid %s", network_event_to_string(msg.trigger),ssid); + ESP_LOGD(TAG, "Posting event %s for ssid %s", network_event_to_string(msg.trigger), ssid); xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } void network_async_connect(const char* ssid, const char* password) { @@ -516,9 +495,7 @@ void network_async_connect(const char* ssid, const char* password) { memset(&msg, 0x00, sizeof(msg)); msg.trigger = EN_CONNECT_NEW; msg.ctx.credentials.ssid = strdup_psram(ssid); - if (password && strlen(password) > 0) { - msg.ctx.credentials.password = strdup_psram(password); - } + if(password && strlen(password) > 0) { msg.ctx.credentials.password = strdup_psram(password); } ESP_LOGD(TAG, "Posting event %s", network_event_to_string(msg.trigger)); xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } @@ -537,7 +514,7 @@ void network_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_e msg.trigger = EN_LOST_CONNECTION; ESP_LOGD(TAG, "Posting event %s", network_event_to_string(msg.trigger)); msg.ctx.disconnected_event = clone_obj_psram(disconnected_event, sizeof(wifi_event_sta_disconnected_t)); - if (msg.ctx.disconnected_event) { + if(msg.ctx.disconnected_event) { xSafeQueueSendToBack(network_queue, &msg, portMAX_DELAY); } else { ESP_LOGE(TAG, "Unable to post lost connection event."); @@ -576,7 +553,7 @@ void network_reboot_ota(char* url) { queue_message msg; memset(&msg, 0x00, sizeof(msg)); - if (url == NULL) { + if(url == NULL) { msg.trigger = EN_REBOOT; msg.ctx.rtype = OTA; ESP_LOGD(TAG, "Posting event %s - type %d", network_event_to_string(msg.trigger), msg.ctx.rtype); @@ -593,9 +570,9 @@ network_t* network_get_state_machine() { return &NM; } static void network_timer_cb(TimerHandle_t timer_id) { network_async_timer(); } esp_netif_t* network_get_active_interface() { - if (NM.wifi_ap_netif && (network_wifi_is_ap_mode() || network_wifi_is_ap_sta_mode())) { + if(NM.wifi_ap_netif && (network_wifi_is_ap_mode() || network_wifi_is_ap_sta_mode())) { return NM.wifi_ap_netif; - } else if (NM.wifi_netif && network_wifi_is_sta_mode()) { + } else if(NM.wifi_netif && network_wifi_is_sta_mode()) { return NM.wifi_netif; } return NM.eth_netif; @@ -603,19 +580,15 @@ esp_netif_t* network_get_active_interface() { bool network_is_interface_connected(esp_netif_t* interface) { esp_err_t err = ESP_OK; tcpip_adapter_ip_info_t ipInfo; - if (!interface) { - return false; - } + if(!interface) { return false; } err = network_get_ip_info_for_netif(interface, &ipInfo); - if (err != ESP_OK) { - ESP_LOGD(TAG, "network_get_ip_info_for_netif returned %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { ESP_LOGD(TAG, "network_get_ip_info_for_netif returned %s", esp_err_to_name(err)); } return ((err == ESP_OK) && (ipInfo.ip.addr != IPADDR_ANY)); } static esp_netif_t* get_connected_interface() { esp_netif_t* interface = NULL; - for (int i = 0; i < 4; i++) { - switch (i) { + for(int i = 0; i < 4; i++) { + switch(i) { case 0: // try the active interface interface = network_get_active_interface(); @@ -632,7 +605,7 @@ static esp_netif_t* get_connected_interface() { default: break; } - if (interface && network_is_interface_connected(interface)) { + if(interface && network_is_interface_connected(interface)) { ESP_LOGD(TAG, "Found connected interface in iteration #%d", i); return interface; } @@ -642,20 +615,20 @@ static esp_netif_t* get_connected_interface() { } esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_info_t* ipInfo) { esp_netif_ip_info_t loc_ip_info; - ESP_LOGD(TAG,"%s Getting IP info","network_get_ip_info_for_netif"); - if (!ipInfo) { + ESP_LOGD(TAG, "%s Getting IP info", "network_get_ip_info_for_netif"); + if(!ipInfo) { ESP_LOGE(TAG, "Invalid pointer for ipInfo"); return ESP_ERR_INVALID_ARG; } - if (!netif) { + if(!netif) { ESP_LOGE(TAG, "Invalid pointer for netif"); return ESP_ERR_INVALID_ARG; } - ESP_LOGD(TAG,"%s Pointers were valid","network_get_ip_info_for_netif"); + ESP_LOGD(TAG, "%s Pointers were valid", "network_get_ip_info_for_netif"); memset(ipInfo, 0x00, sizeof(tcpip_adapter_ip_info_t)); esp_err_t err = esp_netif_get_ip_info(netif, &loc_ip_info); - if (err == ESP_OK) { - ESP_LOGD(TAG,"%s Setting ip4 address","network_get_ip_info_for_netif"); + if(err == ESP_OK) { + ESP_LOGD(TAG, "%s Setting ip4 address", "network_get_ip_info_for_netif"); ip4_addr_set(&(ipInfo->ip), &loc_ip_info.ip); ip4_addr_set(&(ipInfo->gw), &loc_ip_info.gw); ip4_addr_set(&(ipInfo->netmask), &loc_ip_info.netmask); @@ -664,21 +637,19 @@ esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_inf } esp_err_t network_get_ip_info(tcpip_adapter_ip_info_t* ipInfo) { esp_netif_t* netif = get_connected_interface(); - if (netif) { - return network_get_ip_info_for_netif(netif, ipInfo); - } + if(netif) { return network_get_ip_info_for_netif(netif, ipInfo); } return ESP_FAIL; } esp_err_t network_get_hostname(const char** hostname) { return esp_netif_get_hostname(get_connected_interface(), hostname); } void network_set_timer(uint16_t duration, const char* tag) { - if (duration > 0) { - if (tag) { + if(duration > 0) { + if(tag) { ESP_LOGD(TAG, "Setting timer tag to %s", tag); NM.timer_tag = strdup_psram(tag); } - if (!NM.state_timer) { + if(!NM.state_timer) { ESP_LOGD(TAG, "Starting %s timer with period of %u ms.", STR_OR_ALT(NM.timer_tag, "anonymous"), duration); NM.state_timer = xTimerCreate("background STA", pdMS_TO_TICKS(duration), pdFALSE, NULL, network_timer_cb); } else { @@ -686,7 +657,7 @@ void network_set_timer(uint16_t duration, const char* tag) { xTimerChangePeriod(NM.state_timer, pdMS_TO_TICKS(duration), portMAX_DELAY); } xTimerStart(NM.state_timer, portMAX_DELAY); - } else if (NM.state_timer) { + } else if(NM.state_timer) { ESP_LOGD(TAG, "Stopping timer %s", STR_OR_ALT(NM.timer_tag, "anonymous")); xTimerStop(NM.state_timer, portMAX_DELAY); FREE_AND_NULL(NM.timer_tag); @@ -694,12 +665,12 @@ void network_set_timer(uint16_t duration, const char* tag) { } void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { ip_event_got_ip_t* s = NULL; - if (event_base != IP_EVENT) return; - switch (event_id) { + if(event_base != IP_EVENT) return; + switch(event_id) { case IP_EVENT_ETH_GOT_IP: case IP_EVENT_STA_GOT_IP: s = (ip_event_got_ip_t*)event_data; - network_async_got_ip(event_id== IP_EVENT_ETH_GOT_IP ? EN_ETH_GOT_IP : EN_GOT_IP,s); + network_async_got_ip(event_id == IP_EVENT_ETH_GOT_IP ? EN_ETH_GOT_IP : EN_GOT_IP, s); break; case IP_EVENT_STA_LOST_IP: ESP_LOGD(TAG, "IP_EVENT_STA_LOST_IP"); @@ -719,14 +690,14 @@ void network_set_hostname(esp_netif_t* interface) { ESP_LOGD(TAG, "network_set_hostname. Retrieving host name from config structure"); char* temp = NULL; - if (!platform || !platform->has_names || strlen(platform->names.device) == 0) { + if(!platform || !platform->has_names || strlen(platform->names.device) == 0) { temp = alloc_get_fallback_unique_name(); ESP_LOGE(TAG, "Device name not set. Falling back to %s", temp); } ESP_LOGD(TAG, "Setting host name to : %s", temp ? temp : platform->names.device); - if ((err = esp_netif_set_hostname(interface, temp ? temp : platform->names.device)) != ESP_OK) { + if((err = esp_netif_set_hostname(interface, temp ? temp : platform->names.device)) != ESP_OK) { ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err)); } - if (temp) free(temp); + if(temp) free(temp); } diff --git a/components/wifi-manager/network_manager.h b/components/wifi-manager/network_manager.h index 9b228d4c..b8af07ec 100644 --- a/components/wifi-manager/network_manager.h +++ b/components/wifi-manager/network_manager.h @@ -38,36 +38,34 @@ extern "C" { #endif //! List of oven events -#define ALL_NM_EVENTS \ - ADD_FIRST_EVENT(EN_LINK_UP) \ - ADD_EVENT(EN_LINK_DOWN)\ - ADD_EVENT(EN_CONFIGURE)\ - ADD_EVENT(EN_GOT_IP)\ - ADD_EVENT(EN_ETH_GOT_IP)\ - ADD_EVENT(EN_DELETE)\ - ADD_EVENT(EN_REMOVE)\ - ADD_EVENT(EN_TIMER)\ - ADD_EVENT(EN_START)\ - ADD_EVENT(EN_SCAN)\ - ADD_EVENT(EN_FAIL)\ - ADD_EVENT(EN_SUCCESS)\ - ADD_EVENT(EN_SCAN_DONE)\ - ADD_EVENT(EN_CONNECT)\ - ADD_EVENT(EN_CONNECT_NEW)\ - ADD_EVENT(EN_ADD)\ - ADD_EVENT(EN_REBOOT)\ - ADD_EVENT(EN_REBOOT_URL)\ - ADD_EVENT(EN_LOST_CONNECTION)\ - ADD_EVENT(EN_ETHERNET_FALLBACK)\ - ADD_EVENT(EN_UPDATE_STATUS)\ - ADD_EVENT(EN_CONNECTED)\ - ADD_EVENT(EN_COMMIT_CHANGES)\ +#define ALL_NM_EVENTS \ + ADD_FIRST_EVENT(EN_LINK_UP) \ + ADD_EVENT(EN_LINK_DOWN) \ + ADD_EVENT(EN_CONFIGURE) \ + ADD_EVENT(EN_GOT_IP) \ + ADD_EVENT(EN_ETH_GOT_IP) \ + ADD_EVENT(EN_DELETE) \ + ADD_EVENT(EN_REMOVE) \ + ADD_EVENT(EN_TIMER) \ + ADD_EVENT(EN_START) \ + ADD_EVENT(EN_SCAN) \ + ADD_EVENT(EN_FAIL) \ + ADD_EVENT(EN_SUCCESS) \ + ADD_EVENT(EN_SCAN_DONE) \ + ADD_EVENT(EN_CONNECT) \ + ADD_EVENT(EN_CONNECT_NEW) \ + ADD_EVENT(EN_ADD) \ + ADD_EVENT(EN_REBOOT) \ + ADD_EVENT(EN_REBOOT_URL) \ + ADD_EVENT(EN_LOST_CONNECTION) \ + ADD_EVENT(EN_ETHERNET_FALLBACK) \ + ADD_EVENT(EN_UPDATE_STATUS) \ + ADD_EVENT(EN_CONNECTED) \ + ADD_EVENT(EN_COMMIT_CHANGES) \ ADD_EVENT(EN_EXECUTE_CALLBACK) #define ADD_EVENT(name) name, -#define ADD_FIRST_EVENT(name) name=1, -typedef enum { - ALL_NM_EVENTS -} network_event_t; +#define ADD_FIRST_EVENT(name) name = 1, +typedef enum { ALL_NM_EVENTS } network_event_t; #undef ADD_EVENT #undef ADD_FIRST_EVENT @@ -77,23 +75,22 @@ typedef enum { RESTART, } reboot_type_t; -typedef void (*network_manager_cb_t)(void * ctx); -typedef esp_err_t (*network_manager_ret_cb_t)(void * ctx); +typedef void (*network_manager_cb_t)(void* ctx); +typedef esp_err_t (*network_manager_ret_cb_t)(void* ctx); typedef struct { - void * ctx; + void* ctx; network_manager_cb_t cb; network_manager_ret_cb_t ret_cb; } callback_ctx_t; typedef struct { - char * ssid; - char * password; + char* ssid; + char* password; } network_credentials_t; typedef struct { network_event_t trigger; - union - { + union { reboot_type_t rtype; char* strval; wifi_event_sta_disconnected_t* disconnected_event; @@ -101,46 +98,43 @@ typedef struct { network_credentials_t credentials; ip_event_got_ip_t* got_ip_event_data; } ctx; - - esp_netif_t *netif; - + + esp_netif_t* netif; + } queue_message; -typedef struct -{ - state_machine_t Machine; //!< Abstract state machine - const state_t* source_state; +typedef struct { + state_machine_t Machine; //!< Abstract state machine + const state_t* source_state; bool ethernet_connected; TimerHandle_t state_timer; uint32_t STA_duration; - int32_t total_connected_time; - int64_t last_connected; - uint16_t num_disconnect; - uint16_t retries; + int32_t total_connected_time; + int64_t last_connected; + uint16_t num_disconnect; + uint16_t retries; uint16_t initial_retries; bool wifi_connected; - esp_netif_t *wifi_netif; - esp_netif_t *eth_netif; - esp_netif_t *wifi_ap_netif; + esp_netif_t* wifi_netif; + esp_netif_t* eth_netif; + esp_netif_t* wifi_ap_netif; uint16_t sta_polling_min_ms; uint16_t sta_polling_max_ms; uint16_t ap_duration_ms; uint16_t eth_link_down_reboot_ms; uint16_t dhcp_timeout; - uint16_t wifi_dhcp_fail_ms; - queue_message * event_parameters; - char * timer_tag; + uint16_t wifi_dhcp_fail_ms; + queue_message* event_parameters; + char* timer_tag; } network_t; - /* * --------------------- External function prototype --------------------- */ void network_initialize_task(); - -network_t * network_get_state_machine(); +network_t* network_get_state_machine(); void network_event_simple(network_event_t trigger); void network_event(network_event_t trigger, void* param); void network_async_event(network_event_t trigger, void* param); @@ -151,25 +145,25 @@ void network_async_success(); void network_async_link_up(); void network_async_link_down(); void network_async_configure(); -void network_async_got_ip(network_event_t trigger,ip_event_got_ip_t*event_data); +void network_async_got_ip(network_event_t trigger, ip_event_got_ip_t* event_data); void network_async_timer(); void network_async_add(const char* ssid, const char* password); void network_async_commit_protowrapper(void* protoWrapperBase); void network_async_scan(); void network_async_scan_done(); -void network_async_connect(const char * ssid, const char * password); -void network_async_delete_connection(const char * ssid); -void network_async_lost_connection(wifi_event_sta_disconnected_t * disconnected_event); +void network_async_connect(const char* ssid, const char* password); +void network_async_delete_connection(const char* ssid); +void network_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_event); void network_async_reboot(reboot_type_t rtype); void network_reboot_ota(char* url); void network_async_delete(); void network_async_update_status(); void network_async_eth_got_ip(); void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); -bool network_is_interface_connected(esp_netif_t * interface); +bool network_is_interface_connected(esp_netif_t* interface); void network_check_recovery_running(); -void network_async_callback(void * ctx, network_manager_cb_t cb); -void network_async_callback_withret(void * ctx, network_manager_ret_cb_t cb); +void network_async_callback(void* ctx, network_manager_cb_t cb); +void network_async_callback_withret(void* ctx, network_manager_ret_cb_t cb); const char* network_event_to_string(network_event_t state); void network_initialize_state_machine_globals(); @@ -178,34 +172,28 @@ void network_initialize_state_machine_globals(); * @see esp_wifi_types.h * @warning if set to WIFI_AUTH_OPEN, passowrd me be empty. See DEFAULT_AP_PASSWORD. */ -#define AP_AUTHMODE WIFI_AUTH_WPA2_PSK +#define AP_AUTHMODE WIFI_AUTH_WPA2_PSK /** @brief Defines visibility of the access point. 0: visible AP. 1: hidden */ -#define DEFAULT_AP_SSID_HIDDEN 0 +#define DEFAULT_AP_SSID_HIDDEN 0 /** @brief Defines access point's name. Default value: esp32. Run 'make menuconfig' to setup your own value or replace here by a string */ -#define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID - - +#define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID /** @brief Defines access point's bandwidth. * Value: WIFI_BW_HT20 for 20 MHz or WIFI_BW_HT40 for 40 MHz * 20 MHz minimize channel interference but is not suitable for * applications with high data speeds */ -#define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20 +#define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20 +#define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL -#define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL +#define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY +#define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK -#define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY - -#define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK - - -void network_reboot_ota(char * url); - +void network_reboot_ota(char* url); /** * @brief simplified reason codes for a lost connection. @@ -219,11 +207,6 @@ void network_reboot_ota(char * url); * UPDATE_ETHERNET_CONNECTED = 5 */ - - - - - /** * Frees up all memory allocated by the wifi_manager and kill the task. */ @@ -232,23 +215,19 @@ void network_destroy(); /** * Filters the AP scan list to unique SSIDs */ -void filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num); - - +void filter_unique(wifi_ap_record_t* aplist, uint16_t* ap_num); /** * @brief Start the mDNS service */ void network_manager_initialise_mdns(); - - /** * @brief Register a callback to a custom function when specific network manager states are reached. */ bool network_is_wifi_prioritized(); -void network_set_timer(uint16_t duration, const char * tag); -void network_set_hostname(esp_netif_t * netif); +void network_set_timer(uint16_t duration, const char* tag); +void network_set_hostname(esp_netif_t* netif); esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_info_t* ipInfo); void network_start_stop_dhcp_client(esp_netif_t* netif, bool start); void network_start_stop_dhcps(esp_netif_t* netif, bool start); @@ -256,45 +235,56 @@ void network_prioritize_wifi(bool activate); #define ADD_ROOT_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name) #define ADD_ROOT_LEAF_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name) #define ADD_LEAF_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name) -#define ADD_STATE_FORWARD_DECLARATION_(name) \ - static state_machine_result_t name##_handler(state_machine_t* const State_Machine); \ - static state_machine_result_t name##_entry_handler(state_machine_t* const State_Machine); \ +#define ADD_STATE_FORWARD_DECLARATION_(name) \ + static state_machine_result_t name##_handler(state_machine_t* const State_Machine); \ + static state_machine_result_t name##_entry_handler(state_machine_t* const State_Machine); \ static state_machine_result_t name##_exit_handler(state_machine_t* const State_Machine); void initialize_network_handlers(state_machine_t* state_machine); -void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, state_t const * from_state, state_t const* current_state, network_event_t event,bool show_source, const char * caller ); -void network_manager_format_state_machine(esp_log_level_t level, const char* prefix, state_machine_t * state_machine, bool show_source, const char * caller) ; +void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, state_t const* from_state, state_t const* current_state, + network_event_t event, bool show_source, const char* caller); +void network_manager_format_state_machine( + esp_log_level_t level, const char* prefix, state_machine_t* state_machine, bool show_source, const char* caller); -#if defined(LOG_LOCAL_LEVEL) -#if LOG_LOCAL_LEVEL >=5 -#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) network_manager_format_from_to_states(ESP_LOG_VERBOSE, prefix, source,target, event, print_source,caller ) -#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller) network_manager_format_state_machine(ESP_LOG_DEBUG,cb_prefix,state_machine,print_from,caller) -#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__); -#define network_handler_entry_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"ENTRY START":"ENTRY END",State_Machine,false,__FUNCTION__) -#define network_exit_handler_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"EXIT START":"END END",State_Machine,false,__FUNCTION__) -#define network_handler_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"HANDLER START":"HANDLER END",State_Machine,false,__FUNCTION__) +#if defined(LOG_LOCAL_LEVEL) +#if LOG_LOCAL_LEVEL >= 5 +#define NETWORK_PRINT_TRANSITION(begin, prefix, source, target, event, print_source, caller) \ + network_manager_format_from_to_states(ESP_LOG_VERBOSE, prefix, source, target, event, print_source, caller) +#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix, state_machine, print_from, caller) \ + network_manager_format_state_machine(ESP_LOG_DEBUG, cb_prefix, state_machine, print_from, caller) +#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch, __FUNCTION__); +#define network_handler_entry_print(State_Machine, begin) \ + network_manager_format_state_machine(ESP_LOG_DEBUG, begin ? "ENTRY START" : "ENTRY END", State_Machine, false, __FUNCTION__) +#define network_exit_handler_print(State_Machine, begin) \ + network_manager_format_state_machine(ESP_LOG_DEBUG, begin ? "EXIT START" : "END END", State_Machine, false, __FUNCTION__) +#define network_handler_print(State_Machine, begin) \ + network_manager_format_state_machine(ESP_LOG_DEBUG, begin ? "HANDLER START" : "HANDLER END", State_Machine, false, __FUNCTION__) #elif LOG_LOCAL_LEVEL >= 4 -#define network_handler_entry_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"BEGIN ENTRY":"END ENTRY",State_Machine,false,"") -#define network_exit_handler_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"BEGIN EXIT":"END EXIT",State_Machine,false,"") -#define network_handler_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"HANDLER START":"HANDLER END",State_Machine,false,"") +#define network_handler_entry_print(State_Machine, begin) \ + if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG, begin ? "BEGIN ENTRY" : "END ENTRY", State_Machine, false, "") +#define network_exit_handler_print(State_Machine, begin) \ + if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG, begin ? "BEGIN EXIT" : "END EXIT", State_Machine, false, "") +#define network_handler_print(State_Machine, begin) \ + if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG, begin ? "HANDLER START" : "HANDLER END", State_Machine, false, "") -#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) if(begin) network_manager_format_from_to_states(ESP_LOG_DEBUG, prefix, source,target, event, print_source,caller ) -#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__); -#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,cb_prefix,state_machine,print_from,caller) +#define NETWORK_PRINT_TRANSITION(begin, prefix, source, target, event, print_source, caller) \ + if(begin) network_manager_format_from_to_states(ESP_LOG_DEBUG, prefix, source, target, event, print_source, caller) +#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch, __FUNCTION__); +#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix, state_machine, print_from, caller) \ + if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG, cb_prefix, state_machine, print_from, caller) +#endif #endif -#endif #ifndef NETWORK_PRINT_TRANSITION #define network_exit_handler_print(nm, begin) -#define network_handler_entry_print(State_Machine, begin) +#define network_handler_entry_print(State_Machine, begin) #define network_handler_print(State_Machine, begin) -#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,NULL) -#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) -#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller) +#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch, NULL) +#define NETWORK_PRINT_TRANSITION(begin, prefix, source, target, event, print_source, caller) +#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix, state_machine, print_from, caller) #endif #ifdef __cplusplus } #endif - diff --git a/components/wifi-manager/network_manager_handlers.c b/components/wifi-manager/network_manager_handlers.c index a8f3a993..65586c14 100644 --- a/components/wifi-manager/network_manager_handlers.c +++ b/components/wifi-manager/network_manager_handlers.c @@ -130,20 +130,20 @@ static void network_handle_got_ip(network_event_t trigger, ip_event_got_ip_t* ev event_data->ip_changed ? "Address was changed" : "Address unchanged"); } #define HANDLE_GLOBAL_EVENT(m) \ - if (handle_global_event(m) == EVENT_HANDLED) return EVENT_HANDLED; + if(handle_global_event(m) == EVENT_HANDLED) return EVENT_HANDLED; static void network_connect_active_ssid(state_machine_t* const State_Machine) { network_t* const nm = (network_t*)State_Machine; esp_err_t err = network_wifi_connect_active_ssid(); - if (err != ESP_OK) { + if(err != ESP_OK) { nm->wifi_connected = false; - if (err == ESP_ERR_NOT_FOUND) { + if(err == ESP_ERR_NOT_FOUND) { network_async_fail(); } else { ESP_LOGE(TAG, "Oups. Something went wrong while trying to connect to the active ssid!"); ESP_LOGD(TAG, "Checking if ethernet interface is connected"); - if (network_is_interface_connected(nm->eth_netif)) { + if(network_is_interface_connected(nm->eth_netif)) { ESP_LOGD(TAG, "Ethernet connection is found. Try to fallback there"); network_async(EN_ETHERNET_FALLBACK); } else { @@ -166,7 +166,7 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine esp_err_t err = ESP_OK; state_machine_result_t result = EVENT_UN_HANDLED; ESP_LOGD(TAG, "Processing event %s", network_event_to_string(net_sm->Machine.Event)); - switch (net_sm->Machine.Event) { + switch(net_sm->Machine.Event) { case EN_UPDATE_STATUS: // handle the event, but don't swicth // todo: fix this @@ -175,7 +175,7 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine /* code */ break; case EN_REMOVE: - if (net_sm->event_parameters->ctx.credentials.ssid && strlen(net_sm->event_parameters->ctx.credentials.ssid) > 0) { + if(net_sm->event_parameters->ctx.credentials.ssid && strlen(net_sm->event_parameters->ctx.credentials.ssid) > 0) { ESP_LOGD(TAG, "Deleting ssid credentials for %s", net_sm->event_parameters->ctx.credentials.ssid); result = network_wifi_remove_ssid(net_sm->event_parameters->ctx.credentials.ssid) == ESP_OK ? EVENT_HANDLED : EVENT_UN_HANDLED; FREE_AND_NULL(net_sm->event_parameters->ctx.credentials.ssid); @@ -183,7 +183,7 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine return result; break; case EN_ADD: - if (net_sm->event_parameters->ctx.credentials.ssid && strlen(net_sm->event_parameters->ctx.credentials.ssid) > 0) { + if(net_sm->event_parameters->ctx.credentials.ssid && strlen(net_sm->event_parameters->ctx.credentials.ssid) > 0) { ESP_LOGD(TAG, "Adding ssid credentials for %s, password %s", net_sm->event_parameters->ctx.credentials.ssid, STR_OR_BLANK(net_sm->event_parameters->ctx.credentials.password)); result = @@ -199,7 +199,7 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine break; case EN_REBOOT: ESP_LOGD(TAG, "Called for reboot type %d", net_sm->event_parameters->ctx.rtype); - switch (net_sm->event_parameters->ctx.rtype) { + switch(net_sm->event_parameters->ctx.rtype) { case OTA: ESP_LOGD(TAG, " Calling guided_restart_ota."); guided_restart_ota(); @@ -222,7 +222,7 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine return EVENT_HANDLED; break; case EN_REBOOT_URL: - if (net_sm->event_parameters->ctx.strval) { + if(net_sm->event_parameters->ctx.strval) { start_ota(net_sm->event_parameters->ctx.strval, NULL, 0); FREE_AND_NULL(net_sm->event_parameters->ctx.strval); } @@ -234,18 +234,18 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine break; case EN_EXECUTE_CALLBACK: ESP_LOGD(TAG, "Executing Callback"); - if (!net_sm->event_parameters->ctx.cb_ctx.cb && !net_sm->event_parameters->ctx.cb_ctx.ret_cb) { + if(!net_sm->event_parameters->ctx.cb_ctx.cb && !net_sm->event_parameters->ctx.cb_ctx.ret_cb) { ESP_LOGE(TAG, "Invalid callback"); return EVENT_UN_HANDLED; - } else if (net_sm->event_parameters->ctx.cb_ctx.cb) { + } else if(net_sm->event_parameters->ctx.cb_ctx.cb) { ESP_LOGD(TAG, "Executing Callback with no return value"); net_sm->event_parameters->ctx.cb_ctx.cb(net_sm->event_parameters->ctx.cb_ctx.ctx); ESP_LOGD(TAG, "Done executing callback"); return EVENT_HANDLED; - } else if (net_sm->event_parameters->ctx.cb_ctx.ret_cb) { + } else if(net_sm->event_parameters->ctx.cb_ctx.ret_cb) { ESP_LOGD(TAG, "Executing Callback with return value"); err = net_sm->event_parameters->ctx.cb_ctx.ret_cb(net_sm->event_parameters->ctx.cb_ctx.ctx); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "Error processing event"); return EVENT_UN_HANDLED; } @@ -286,20 +286,18 @@ static state_machine_result_t NETWORK_INSTANTIATED_STATE_handler(state_machine_t "%d, eth timeout %d", nm->sta_polling_max_ms, nm->sta_polling_min_ms, nm->ap_duration_ms, nm->dhcp_timeout, nm->eth_link_down_reboot_ms); HANDLE_GLOBAL_EVENT(State_Machine); - #ifndef TESTPROJECT - if(!platform){ - ESP_LOGE(TAG,"Configuration not initialized."); - } - else - { - if (platform && State_Machine->Event == EN_START) { +#ifndef TESTPROJECT + if(!platform) { + ESP_LOGE(TAG, "Configuration not initialized."); + } else { + if(platform && State_Machine->Event == EN_START) { result = local_traverse_state(State_Machine, &network_states[NETWORK_INITIALIZING_STATE], __FUNCTION__); } - } - #else - ESP_LOGI(TAG,"network message ignored in test mode"); - result= EVENT_HANDLED; - #endif + } +#else + ESP_LOGI(TAG, "network message ignored in test mode"); + result = EVENT_HANDLED; +#endif network_handler_print(State_Machine, false); return result; @@ -318,7 +316,7 @@ static state_machine_result_t NETWORK_INITIALIZING_STATE_entry_handler(state_mac // Initialize nvs; this is needed by the wifi driver ESP_LOGI(TAG, "Initializing flash nvs "); esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "%s. Erasing nvs flash", esp_err_to_name(err)); ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); @@ -340,12 +338,12 @@ static state_machine_result_t NETWORK_INITIALIZING_STATE_handler(state_machine_t network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_UN_HANDLED; HANDLE_GLOBAL_EVENT(State_Machine); - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_START: - if (network_is_wifi_prioritized()) { + if(network_is_wifi_prioritized()) { ESP_LOGI(TAG, "WiFi connection is prioritized. Starting WiFi"); result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); - } else if (is_recovery_running) { + } else if(is_recovery_running) { ESP_LOGI(TAG, "Running recovery. Skipping ethernet, starting WiFi"); result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); } else { @@ -372,7 +370,7 @@ static state_machine_result_t ETH_STARTING_STATE_entry_handler(state_machine_t* ESP_LOGD(TAG, "Looking for ethernet Interface"); network_t* const nm = (network_t*)State_Machine; init_network_ethernet(); - if (!network_ethernet_enabled()) { + if(!network_ethernet_enabled()) { network_async_fail(); } else { nm->eth_netif = network_ethernet_get_interface(); @@ -386,7 +384,7 @@ static state_machine_result_t ETH_STARTING_STATE_handler(state_machine_t* const state_machine_result_t result = EVENT_HANDLED; network_handler_print(State_Machine, true); HANDLE_GLOBAL_EVENT(State_Machine); - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_FAIL: result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); break; @@ -412,9 +410,9 @@ static state_machine_result_t ETH_STARTING_STATE_exit_handler(state_machine_t* c static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) { network_handler_entry_print(State_Machine, true); network_t* const nm = (network_t*)State_Machine; - ESP_LOGD(TAG,"Entering ETH Active state. Setting timer"); + ESP_LOGD(TAG, "Entering ETH Active state. Setting timer"); network_set_timer(nm->eth_link_down_reboot_ms, "Ethernet link not detected"); - ESP_LOGD(TAG,"Entering ETH Active state. Executing callback(s)"); + ESP_LOGD(TAG, "Entering ETH Active state. Executing callback(s)"); NETWORK_EXECUTE_CB(State_Machine); network_handler_entry_print(State_Machine, false); return EVENT_HANDLED; @@ -424,7 +422,7 @@ static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_handler(state_machine_t* state_machine_result_t result = EVENT_UN_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_CONNECT_NEW: result = local_traverse_state(State_Machine, &Eth_Active_State[ETH_CONNECTING_NEW_STATE], __FUNCTION__); break; @@ -496,7 +494,7 @@ static state_machine_result_t ETH_CONNECTING_NEW_STATE_handler(state_machine_t* state_machine_result_t result = EVENT_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_GOT_IP: network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); @@ -589,7 +587,7 @@ static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_handler(state_machine_t* network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_UN_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_LINK_UP: ESP_LOGW(TAG, "Ethernet link up in wifi mode"); break; @@ -606,14 +604,10 @@ static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_handler(state_machine_t* result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE], __FUNCTION__); break; case EN_SCAN: - if (network_wifi_start_scan() == ESP_OK) { - result = EVENT_HANDLED; - } + if(network_wifi_start_scan() == ESP_OK) { result = EVENT_HANDLED; } break; case EN_SCAN_DONE: - if (wifi_scan_done() == ESP_OK) { - result = EVENT_HANDLED; - } + if(wifi_scan_done() == ESP_OK) { result = EVENT_HANDLED; } network_async_success(); break; case EN_CONNECT_NEW: @@ -644,14 +638,12 @@ static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_exit_handler(state_machi static state_machine_result_t WIFI_INITIALIZING_STATE_entry_handler(state_machine_t* const State_Machine) { network_t* const nm = (network_t*)State_Machine; network_handler_entry_print(State_Machine, true); - if (!nm->wifi_netif) { - nm->wifi_netif = network_wifi_start(); - } - if (!is_wifi_up()) { + if(!nm->wifi_netif) { nm->wifi_netif = network_wifi_start(); } + if(!is_wifi_up()) { messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Load Configuration"); return EVENT_UN_HANDLED; } - if (network_wifi_get_known_count() > 0) { + if(network_wifi_get_known_count() > 0) { ESP_LOGI(TAG, "Existing wifi config found. Attempting to connect."); network_async_success(); } else { @@ -668,7 +660,7 @@ static state_machine_result_t WIFI_INITIALIZING_STATE_handler(state_machine_t* c HANDLE_GLOBAL_EVENT(State_Machine); network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_CONFIGURE: result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); break; @@ -706,17 +698,13 @@ static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_handler(stat network_t* const nm = (network_t*)State_Machine; state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_SCAN: - if (network_wifi_start_scan() == ESP_OK) { - result = EVENT_HANDLED; - } + if(network_wifi_start_scan() == ESP_OK) { result = EVENT_HANDLED; } break; case EN_SCAN_DONE: ESP_LOGD(TAG, "Network configuration active, wifi scan completed"); - if (wifi_scan_done() == ESP_OK) { - result = EVENT_HANDLED; - } + if(wifi_scan_done() == ESP_OK) { result = EVENT_HANDLED; } break; case EN_CONNECT_NEW: result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_STATE], __FUNCTION__); @@ -787,7 +775,7 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_handler(state_machi network_handler_print(State_Machine, true); network_t* const nm = (network_t*)State_Machine; state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_CONNECTED: result = EVENT_HANDLED; ESP_LOGI(TAG, "Wifi was connected. Waiting for IP address"); @@ -801,7 +789,7 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_handler(state_machi result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_SUCCESS_STATE], __FUNCTION__); break; case EN_LOST_CONNECTION: - if (nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { + if(nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { ESP_LOGI(TAG, "Wifi was disconnected from previous access point. Waiting to connect."); } else { network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); @@ -845,7 +833,7 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_handler(sta network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_UPDATE_STATUS: // todo: fix this // network_status_update_basic_info(); @@ -890,12 +878,12 @@ static state_machine_result_t WIFI_CONNECTING_STATE_handler(state_machine_t* con state_machine_result_t result = EVENT_HANDLED; network_t* const nm = (network_t*)State_Machine; network_handler_print(State_Machine, true); - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_CONNECTED: // nothing to do here. Let's wait for IP address break; case EN_TIMER: - if (nm->initial_retries < (platform!=NULL && platform->net.max_initial_wifi_attempt>0?platform->net.max_initial_wifi_attempt:5)) { + if(nm->initial_retries < (platform != NULL && platform->net.max_initial_wifi_attempt > 0 ? platform->net.max_initial_wifi_attempt : 5)) { nm->initial_retries++; ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->initial_retries, platform->net.max_initial_wifi_attempt); ESP_LOGI(TAG, "Timer: %s ", STR_OR_ALT(nm->timer_tag, "Ethernet link not detected")); @@ -904,11 +892,11 @@ static state_machine_result_t WIFI_CONNECTING_STATE_handler(state_machine_t* con } break; case EN_LOST_CONNECTION: - if (nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE || + if(nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE || nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_AUTH_EXPIRE || nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_EXPIRE) { ESP_LOGI(TAG, "Wifi was disconnected from previous access point. Waiting to connect."); - } else if (nm->event_parameters->ctx.disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) { + } else if(nm->event_parameters->ctx.disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) { network_status_update_ip_info(sys_status_reasons_R_FAILED_ATTEMPT); result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); } @@ -946,7 +934,7 @@ static state_machine_result_t WIFI_CONNECTING_SCAN_STATE_handler(state_machine_t HANDLE_GLOBAL_EVENT(State_Machine); state_machine_result_t result = EVENT_HANDLED; network_handler_print(State_Machine, true); - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_SUCCESS: // scan completed, we can try to connect to a known AP now network_wifi_activate_strongest_ssid(); @@ -984,7 +972,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_STATE_handler(state_machine_t* state_machine_result_t result = EVENT_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_GOT_IP: network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); @@ -997,7 +985,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_STATE_handler(state_machine_t* result = EVENT_HANDLED; break; case EN_LOST_CONNECTION: - if (((network_t*)State_Machine)->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { + if(((network_t*)State_Machine)->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { ESP_LOGD(TAG, "Successfully disconnected from the existing access point. "); return EVENT_HANDLED; } @@ -1026,7 +1014,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_STATE_exit_handler(state_machi static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_entry_handler(state_machine_t* const State_Machine) { network_t* const nm = (network_t*)State_Machine; network_handler_entry_print(State_Machine, true); - if (nm->wifi_connected) { + if(nm->wifi_connected) { // Wifi was already connected to an existing access point. Restore connection network_connect_active_ssid(State_Machine); } @@ -1041,7 +1029,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_handler(state_mac state_machine_result_t result = EVENT_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_GOT_IP: network_handle_got_ip(State_Machine->Event, nm->event_parameters->ctx.got_ip_event_data); FREE_AND_NULL(nm->event_parameters->ctx.got_ip_event_data); @@ -1080,7 +1068,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_exit_handler(stat static state_machine_result_t WIFI_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) { network_t* const nm = (network_t*)State_Machine; network_handler_entry_print(State_Machine, true); - ESP_LOGD(TAG,"Entered WIFI_CONNECTED_STATE "); + ESP_LOGD(TAG, "Entered WIFI_CONNECTED_STATE "); nm->last_connected = esp_timer_get_time(); // cancel timeout pulse network_set_timer(0, NULL); @@ -1095,13 +1083,13 @@ static state_machine_result_t WIFI_CONNECTED_STATE_handler(state_machine_t* cons network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; network_t* const nm = (network_t*)State_Machine; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_LOST_CONNECTION: - if (is_restarting()) { + if(is_restarting()) { // ignore this as we're restarting return EVENT_HANDLED; } - if (nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { + if(nm->event_parameters->ctx.disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) { ESP_LOGD(TAG, "User disconnected from wifi. Re-initializing connection"); result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE], __FUNCTION__); } else { @@ -1140,7 +1128,7 @@ static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_handler(state_machine HANDLE_GLOBAL_EVENT(State_Machine); network_handler_print(State_Machine, true); state_machine_result_t result = EVENT_HANDLED; - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_LOST_CONNECTION: // this is a success! we're actually asking to disconnect result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); @@ -1168,12 +1156,12 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_mac network_status_update_ip_info(sys_status_reasons_R_LOST_CONNECTION); // todo: fix this! // network_status_safe_reset_sta_ip_string(); - if (nm->last_connected > 0) nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000)); + if(nm->last_connected > 0) nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000)); nm->last_connected = 0; nm->num_disconnect++; ESP_LOGW(TAG, " Wifi disconnected. Number of disconnects: %d, Average time connected: %d", nm->num_disconnect, nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0); - if (nm->retries < (platform && platform->net.max_wifi_retry>0?platform->net.max_wifi_retry:5)) { + if(nm->retries < (platform && platform->net.max_wifi_retry > 0 ? platform->net.max_wifi_retry : 5)) { nm->retries++; ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->retries, platform->net.max_wifi_retry); network_async(EN_CONNECT); @@ -1181,7 +1169,7 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_mac /* In this scenario the connection was lost beyond repair */ nm->retries = 0; ESP_LOGD(TAG, "Checking if ethernet interface is connected"); - if (network_is_interface_connected(nm->eth_netif)) { + if(network_is_interface_connected(nm->eth_netif)) { ESP_LOGW(TAG, "Cannot connect to Wifi. Falling back to Ethernet "); network_async(EN_ETHERNET_FALLBACK); } else { @@ -1191,10 +1179,10 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_mac /* put us in softAP mode first */ esp_wifi_get_mode(&mode); - if (WIFI_MODE_APSTA != mode) { + if(WIFI_MODE_APSTA != mode) { nm->STA_duration = nm->sta_polling_min_ms; network_async_configure(); - } else if (nm->STA_duration < nm->sta_polling_max_ms) { + } else if(nm->STA_duration < nm->sta_polling_max_ms) { nm->STA_duration *= 1.25; } @@ -1213,7 +1201,7 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_handler(state_machine_t network_t* const nm = (network_t*)State_Machine; state_machine_result_t result = EVENT_HANDLED; network_handler_print(State_Machine, true); - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_CONFIGURE: result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE], __FUNCTION__); break; @@ -1253,7 +1241,7 @@ static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_handler(state_machine_t HANDLE_GLOBAL_EVENT(State_Machine); state_machine_result_t result = EVENT_HANDLED; network_handler_print(State_Machine, true); - switch (State_Machine->Event) { + switch(State_Machine->Event) { case EN_TIMER: ESP_LOGD(TAG, "Ignoring ethernet link up timer check"); result = EVENT_HANDLED; @@ -1291,16 +1279,16 @@ static void network_interface_coexistence(state_machine_t* state_machine) { // this function is called whenever both wifi and ethernet are // found to be active at the same time network_t* nm = (network_t*)state_machine; - if (nm->wifi_connected && state_machine->Event == EN_ETH_GOT_IP) { + if(nm->wifi_connected && state_machine->Event == EN_ETH_GOT_IP) { network_prioritize_wifi(false); - if (platform && !platform->net.eth_boot) { + if(platform && !platform->net.eth_boot) { ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting"); simple_restart(); } else { ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using " "Wifi interface until next reboot"); } - } else if (get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE) { + } else if(get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE) { messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi Connected with Ethernet active. System reload needed"); simple_restart(); } diff --git a/components/wifi-manager/network_services.h b/components/wifi-manager/network_services.h index 7e2b2fe8..dc8370b4 100644 --- a/components/wifi-manager/network_services.h +++ b/components/wifi-manager/network_services.h @@ -34,51 +34,39 @@ extern "C" { #define ADD_ROOT_LEAF(name, ...) name, #define ADD_LEAF(name, ...) name, -#define ALL_NM_STATE \ - ADD_ROOT_LEAF(NETWORK_INSTANTIATED_STATE)\ - ADD_ROOT_LEAF(NETWORK_INITIALIZING_STATE)\ - ADD_ROOT(NETWORK_ETH_ACTIVE_STATE, Eth_Active_State)\ - ADD_ROOT(NETWORK_WIFI_ACTIVE_STATE, Wifi_Active_State)\ +#define ALL_NM_STATE \ + ADD_ROOT_LEAF(NETWORK_INSTANTIATED_STATE) \ + ADD_ROOT_LEAF(NETWORK_INITIALIZING_STATE) \ + ADD_ROOT(NETWORK_ETH_ACTIVE_STATE, Eth_Active_State) \ + ADD_ROOT(NETWORK_WIFI_ACTIVE_STATE, Wifi_Active_State) \ ADD_ROOT(NETWORK_WIFI_CONFIGURING_ACTIVE_STATE, Wifi_Configuring_State) -#define ALL_ETH_STATE(PARENT, LEVEL)\ - ADD_LEAF(ETH_STARTING_STATE,PARENT,LEVEL)\ - ADD_LEAF(ETH_ACTIVE_LINKUP_STATE,PARENT,LEVEL)\ - ADD_LEAF(ETH_ACTIVE_LINKDOWN_STATE,PARENT,LEVEL)\ - ADD_LEAF(ETH_ACTIVE_CONNECTED_STATE,PARENT,LEVEL)\ - ADD_LEAF(ETH_CONNECTING_NEW_STATE,PARENT,LEVEL) +#define ALL_ETH_STATE(PARENT, LEVEL) \ + ADD_LEAF(ETH_STARTING_STATE, PARENT, LEVEL) \ + ADD_LEAF(ETH_ACTIVE_LINKUP_STATE, PARENT, LEVEL) \ + ADD_LEAF(ETH_ACTIVE_LINKDOWN_STATE, PARENT, LEVEL) \ + ADD_LEAF(ETH_ACTIVE_CONNECTED_STATE, PARENT, LEVEL) \ + ADD_LEAF(ETH_CONNECTING_NEW_STATE, PARENT, LEVEL) -#define ALL_WIFI_STATE(PARENT, LEVEL)\ - ADD_LEAF(WIFI_INITIALIZING_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONNECTING_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONNECTING_SCAN_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONNECTING_NEW_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONNECTING_NEW_FAILED_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONNECTED_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_USER_DISCONNECTED_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_LOST_CONNECTION_STATE,PARENT,LEVEL) +#define ALL_WIFI_STATE(PARENT, LEVEL) \ + ADD_LEAF(WIFI_INITIALIZING_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONNECTING_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONNECTING_SCAN_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONNECTING_NEW_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONNECTING_NEW_FAILED_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONNECTED_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_USER_DISCONNECTED_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_LOST_CONNECTION_STATE, PARENT, LEVEL) -#define ALL_WIFI_CONFIGURING_STATE(PARENT, LEVEL)\ - ADD_LEAF(WIFI_CONFIGURING_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONFIGURING_CONNECT_STATE,PARENT,LEVEL)\ - ADD_LEAF(WIFI_CONFIGURING_CONNECT_SUCCESS_STATE,PARENT,LEVEL) +#define ALL_WIFI_CONFIGURING_STATE(PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONFIGURING_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONFIGURING_CONNECT_STATE, PARENT, LEVEL) \ + ADD_LEAF(WIFI_CONFIGURING_CONNECT_SUCCESS_STATE, PARENT, LEVEL) -typedef enum { - ALL_NM_STATE - TOTAL_NM_STATE -} nm_state_t; -typedef enum { - ALL_WIFI_STATE(,) - TOTAL_WIFI_ACTIVE_STATE -} mn_wifi_active_state_t; -typedef enum { - ALL_ETH_STATE(,) - TOTAL_ETH_ACTIVE_STATE -} mn_eth_active_state_t; -typedef enum { - ALL_WIFI_CONFIGURING_STATE(,) - TOTAL_WIFI_CONFIGURING_STATE -} mn_wifi_configuring_state_t; +typedef enum { ALL_NM_STATE TOTAL_NM_STATE } nm_state_t; +typedef enum { ALL_WIFI_STATE(, ) TOTAL_WIFI_ACTIVE_STATE } mn_wifi_active_state_t; +typedef enum { ALL_ETH_STATE(, ) TOTAL_ETH_ACTIVE_STATE } mn_eth_active_state_t; +typedef enum { ALL_WIFI_CONFIGURING_STATE(, ) TOTAL_WIFI_CONFIGURING_STATE } mn_wifi_configuring_state_t; #undef ADD_STATE #undef ADD_ROOT @@ -88,8 +76,8 @@ typedef enum { typedef void (*network_status_reached_cb)(nm_state_t state_id, int sub_state); esp_err_t network_register_state_callback(nm_state_t state, int sub_state, const char* from, network_status_reached_cb cb); -esp_netif_t * network_get_active_interface(); -esp_err_t network_get_hostname(const char **hostname); +esp_netif_t* network_get_active_interface(); +esp_err_t network_get_hostname(const char** hostname); esp_err_t network_get_ip_info(tcpip_adapter_ip_info_t* ipInfo); #ifdef __cplusplus diff --git a/components/wifi-manager/network_status.cpp b/components/wifi-manager/network_status.cpp index c4d2f6da..30829c85 100644 --- a/components/wifi-manager/network_status.cpp +++ b/components/wifi-manager/network_status.cpp @@ -27,7 +27,7 @@ static const char TAG[] = "network_status"; sys_status_data* sys_status = nullptr; -__attribute__((section(".ext_ram.bss"))) System::PB sys_status_obj("status", &sys_status_data_msg,sizeof(sys_status_data_msg)); +__attribute__((section(".ext_ram.bss"))) System::PB sys_status_obj("status", &sys_status_data_msg, sizeof(sys_status_data_msg)); static void (*chained_notify)(in_addr_t, u16_t, u16_t); static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport); @@ -36,16 +36,13 @@ static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport); void network_status_set_static_info() { ESP_LOGD(TAG, "network_status_set_static_info starting"); - if (sys_status_obj.Lock()) { + if(sys_status_obj.Lock()) { const esp_app_desc_t* desc = esp_ota_get_app_description(); auto status_obj = sys_status_obj.get(); status_obj->has_platform = true; - strncpy( - status_obj->platform.project, desc->project_name, sizeof(status_obj->platform.project)); - if (platform->target && strlen(platform->target) > 0) { - if (status_obj->platform.target) { - free(status_obj->platform.target); - } + strncpy(status_obj->platform.project, desc->project_name, sizeof(status_obj->platform.project)); + if(platform->target && strlen(platform->target) > 0) { + if(status_obj->platform.target) { free(status_obj->platform.target); } status_obj->platform.target = strdup_psram(platform->target); } strncpy(status_obj->platform.version, desc->version, sizeof(status_obj->platform.version)); @@ -55,16 +52,13 @@ void network_status_set_static_info() { status_obj->platform.depth = DEPTH; #endif status_obj->has_hw = true; - status_obj->hw.supports_jack_inserted = platform->gpios.has_jack &&platform->gpios.jack.pin>=0; - status_obj->hw.supports_spk_fault = platform->gpios.has_spkfault && platform->gpios.spkfault.pin>=0; + status_obj->hw.supports_jack_inserted = platform->gpios.has_jack && platform->gpios.jack.pin >= 0; + status_obj->hw.supports_spk_fault = platform->gpios.has_spkfault && platform->gpios.spkfault.pin >= 0; status_obj->has_net = true; status_obj->net.has_wifi = true; #ifdef CONFIG_BT_ENABLED - if (platform->has_services && platform->services.has_bt_sink && - platform->services.bt_sink.enabled) { - status_obj->has_bt = true; - } + if(platform->has_services && platform->services.has_bt_sink && platform->services.bt_sink.enabled) { status_obj->has_bt = true; } #endif ESP_LOGD(TAG, "network_status_set_static_info done"); sys_status_obj.Unlock(); @@ -83,7 +77,7 @@ void init_network_status() { void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport) { sys_net_server* LMS = &sys_status->LMS; - if (sys_status_obj.Lock()) { + if(sys_status_obj.Lock()) { sys_status->has_LMS = true; strncpy(LMS->ip, inet_ntoa(ip), sizeof(LMS->ip)); LMS->port = hport; @@ -95,32 +89,28 @@ void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport) { static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) { set_lms_server_details(ip, hport, cport); - if (chained_notify) (*chained_notify)(ip, hport, cport); + if(chained_notify) (*chained_notify)(ip, hport, cport); network_async_update_status(); } void network_status_set_basic_info() { - if (sys_status_obj.Lock()) { + if(sys_status_obj.Lock()) { network_t* nm = network_get_state_machine(); sys_status->hw.jack_inserted = jack_inserted_svc(); sys_status->hw.spk_fault = spkfault_svc(); sys_status->hw.batt_voltage = battery_value_svc(); sys_status->net.wifi.disconnect_count = nm->num_disconnect; - sys_status->net.wifi.avg_conn_time = - nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0; + sys_status->net.wifi.avg_conn_time = nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0; #ifdef CONFIG_BT_ENABLED - if (platform->has_services && platform->services.has_bt_sink && - platform->services.bt_sink.enabled) { + if(platform->has_services && platform->services.has_bt_sink && platform->services.bt_sink.enabled) { sys_status->has_bt = true; sys_status->bt.bt_status = bt_app_source_get_a2d_state(); sys_status->bt.bt_media_state = bt_app_source_get_media_state(); } #endif - if (network_ethernet_enabled()) { - sys_status->net.eth_up = network_ethernet_is_up(); - } + if(network_ethernet_enabled()) { sys_status->net.eth_up = network_ethernet_is_up(); } ESP_LOGV(TAG, "network_status_get_basic_info done"); sys_status_obj.Unlock(); } else { @@ -128,38 +118,32 @@ void network_status_set_basic_info() { } } void network_status_update_address(esp_netif_ip_info_t* ip_info) { - if (sys_status_obj.Lock()) { + if(sys_status_obj.Lock()) { sys_status->has_net = true; sys_status->net.has_ip = true; - strncpy(sys_status->net.ip.ip, ip4addr_ntoa((ip4_addr_t*)&ip_info->ip), - sizeof(sys_status->net.ip.ip)); - strncpy(sys_status->net.ip.netmask, ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask), - sizeof(sys_status->net.ip.netmask)); - strncpy(sys_status->net.ip.gw, ip4addr_ntoa((ip4_addr_t*)&ip_info->gw), - sizeof(sys_status->net.ip.gw)); + strncpy(sys_status->net.ip.ip, ip4addr_ntoa((ip4_addr_t*)&ip_info->ip), sizeof(sys_status->net.ip.ip)); + strncpy(sys_status->net.ip.netmask, ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask), sizeof(sys_status->net.ip.netmask)); + strncpy(sys_status->net.ip.gw, ip4addr_ntoa((ip4_addr_t*)&ip_info->gw), sizeof(sys_status->net.ip.gw)); sys_status_obj.Unlock(); } } void network_status_update_ip_info(sys_status_reasons update_reason_code) { ESP_LOGV(TAG, "network_status_update_ip_info called"); esp_netif_ip_info_t ip_info; - if (sys_status_obj.Lock()) { + if(sys_status_obj.Lock()) { /* generate the connection info with success */ network_status_set_basic_info(); sys_status->net.updt_reason = update_reason_code; sys_status->net.wifi.has_connected_sta = false; sys_status->net.wifi.connected_sta.connected = false; - ESP_LOGD(TAG, - "Updating ip info with reason code %s. Checking if Wifi interface is connected", - sys_status_reasons_name(update_reason_code)); - if (network_is_interface_connected(network_wifi_get_interface()) || - update_reason_code == sys_status_reasons_R_FAILED_ATTEMPT) { + ESP_LOGD(TAG, "Updating ip info with reason code %s. Checking if Wifi interface is connected", sys_status_reasons_name(update_reason_code)); + if(network_is_interface_connected(network_wifi_get_interface()) || update_reason_code == sys_status_reasons_R_FAILED_ATTEMPT) { sys_status->net.interface = sys_status_interfaces_IF_WIFI; esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info); network_status_update_address(&ip_info); - if (!network_wifi_is_ap_mode()) { + if(!network_wifi_is_ap_mode()) { /* wifi is active, and associated to an AP */ wifi_ap_record_t ap; esp_wifi_sta_get_ap_info(&ap); @@ -170,7 +154,7 @@ void network_status_update_ip_info(sys_status_reasons update_reason_code) { } } ESP_LOGD(TAG, "Checking if ethernet interface is connected"); - if (network_is_interface_connected(network_ethernet_get_interface())) { + if(network_is_interface_connected(network_ethernet_get_interface())) { sys_status->net.interface = sys_status_interfaces_IF_ETHERNET; esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info); network_status_update_address(&ip_info); @@ -186,7 +170,7 @@ bool network_status_send_object(httpd_req_t* req) { auto data = sys_status_obj.Encode(); httpd_resp_send(req, (const char*)data.data(), data.size()); return true; - } catch (const std::runtime_error& e) { + } catch(const std::runtime_error& e) { std::string errdesc = (std::string("Unable to get status: ") + e.what()); httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, errdesc.c_str()); } diff --git a/components/wifi-manager/network_status.h b/components/wifi-manager/network_status.h index 0ffb82dd..87f73c3d 100644 --- a/components/wifi-manager/network_status.h +++ b/components/wifi-manager/network_status.h @@ -30,15 +30,12 @@ #ifdef __cplusplus - extern System::PB sys_status_obj; extern "C" { #endif - - /** * @brief Generates the connection status json: ssid and IP addresses. * @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful. diff --git a/components/wifi-manager/network_wifi.cpp b/components/wifi-manager/network_wifi.cpp index 0ddbe5f1..36aa7cff 100644 --- a/components/wifi-manager/network_wifi.cpp +++ b/components/wifi-manager/network_wifi.cpp @@ -22,7 +22,6 @@ #include #include "esp_sntp.h" - WifiList* wifi_config_aps; EXT_RAM_ATTR WifiList scan_results_aps("scan_results"); @@ -34,11 +33,10 @@ static const char TAG[] = "network_wifi"; esp_netif_t* wifi_netif; esp_netif_t* wifi_ap_netif; extern sys_status_data status; -static void time_sync_notification_cb(struct timeval *tv) -{ +static void time_sync_notification_cb(struct timeval* tv) { ESP_LOGI(TAG, "Notification of a time synchronization event"); wifi_config_aps->UpdateFromClock(); - scan_results_aps.UpdateFromClock(); + scan_results_aps.UpdateFromClock(); } static bool is_initialized() { return (platform != NULL) && platform->has_net; } @@ -66,7 +64,7 @@ static bool is_initialized() { return (platform != NULL) && platform->has_net; } // } size_t network_wifi_get_known_count() { size_t result = 0; - if (!is_initialized()) { + if(!is_initialized()) { ESP_LOGE(TAG, "Config not initialized"); return 0; } @@ -80,7 +78,7 @@ const wifi_sta_config_t* network_wifi_get_active_config() { static wifi_config_t config; esp_err_t err = ESP_OK; memset(&config, 0x00, sizeof(config)); - if ((err = esp_wifi_get_config(WIFI_IF_STA, &config)) == ESP_OK) { + if((err = esp_wifi_get_config(WIFI_IF_STA, &config)) == ESP_OK) { return &config.sta; } else { ESP_LOGD(TAG, "Could not get wifi STA config: %s", esp_err_to_name(err)); @@ -93,31 +91,29 @@ bool network_wifi_is_known_ap(const char* ssid) { return wifi_config_aps->Exists esp_netif_t* network_wifi_get_interface() { return wifi_netif; } esp_netif_t* network_wifi_get_ap_interface() { return wifi_ap_netif; } esp_err_t network_wifi_set_sta_mode() { - if (!wifi_netif) { + if(!wifi_netif) { ESP_LOGE(TAG, "Wifi not initialized. Cannot set sta mode"); return ESP_ERR_INVALID_STATE; } ESP_LOGD(TAG, "Set Mode to STA"); esp_err_t err = esp_wifi_set_mode(WIFI_MODE_STA); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "Error setting mode to STA: %s", esp_err_to_name(err)); } else { ESP_LOGI(TAG, "Starting wifi"); err = esp_wifi_start(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error starting wifi: %s", esp_err_to_name(err)); - } + if(err != ESP_OK) { ESP_LOGE(TAG, "Error starting wifi: %s", esp_err_to_name(err)); } } - ESP_LOGD(TAG,"Done setting wifi mode to STA"); + ESP_LOGD(TAG, "Done setting wifi mode to STA"); return err; } esp_netif_t* network_wifi_start() { esp_err_t err = ESP_OK; - if (!wifi_netif) { + if(!wifi_netif) { wifi_netif = esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); err = esp_wifi_init(&cfg); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "Error initializing wifi: %s", esp_err_to_name(err)); return wifi_netif; } @@ -137,19 +133,19 @@ esp_err_t network_wifi_set_connected(bool connected) { bool state_changed = false; bool config_changed = false; ESP_LOGD(TAG, "Resetting connected list"); - if (wifi_config_aps->Lock()) { + if(wifi_config_aps->Lock()) { wifi_config_aps->ResetConnected(); wifi_config_aps->Unlock(); } ESP_LOGD(TAG, "Erasing connected sta object"); - if (sys_status_obj.get()->net.wifi.has_connected_sta && sys_status_obj.Lock()) { + if(sys_status_obj.get()->net.wifi.has_connected_sta && sys_status_obj.Lock()) { pb_release(&sys_net_wifi_entry_msg, &sys_status_obj.get()->net.wifi.connected_sta); sys_status_obj.get()->net.has_wifi = true; sys_status_obj.get()->has_net = true; sys_status_obj.get()->net.wifi.has_connected_sta = false; sys_status_obj.Unlock(); } - if (stateWrapper.get()->has_connected_sta && stateWrapper.Lock()) { + if(stateWrapper.get()->has_connected_sta && stateWrapper.Lock()) { pb_release(&sys_net_wifi_entry_msg, stateWrapper.get()); stateWrapper.get()->has_connected_sta = false; stateWrapper.Unlock(); @@ -157,15 +153,15 @@ esp_err_t network_wifi_set_connected(bool connected) { } esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "Error retrieving wifi config"); } else { - if (!connected) { + if(!connected) { ESP_LOGI(TAG, "Connected list was reset"); } else { ESP_LOGI(TAG, "Updating connected sta to %s", WifiList::GetSSID(&config.sta).c_str()); ESP_LOGD(TAG, "Locking credentials manager"); - if (wifi_config_aps->Lock()) { + if(wifi_config_aps->Lock()) { ESP_LOGD(TAG, "Adding/updating credentials"); wifi_config_aps->AddUpdate(&config.sta).connected = true; ESP_LOGD(TAG, "Unlocking credentials manager"); @@ -174,19 +170,19 @@ esp_err_t network_wifi_set_connected(bool connected) { } } } - if (config_changed) { + if(config_changed) { ESP_LOGD(TAG, "Raising changed event on the config wrapper object"); configWrapper.RaiseChangedAsync(); } - if (state_changed) { + if(state_changed) { ESP_LOGD(TAG, "Raising changed event on the state wrapper object"); stateWrapper.RaiseChangedAsync(); } return err; } static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { - if (event_base != WIFI_EVENT) return; - switch (event_id) { + if(event_base != WIFI_EVENT) return; + switch(event_id) { case WIFI_EVENT_WIFI_READY: ESP_LOGD(TAG, "WIFI_EVENT_WIFI_READY"); @@ -212,9 +208,7 @@ static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, i case WIFI_EVENT_AP_PROBEREQRECVED: { wifi_event_ap_probe_req_rx_t* s = (wifi_event_ap_probe_req_rx_t*)event_data; char* mac = alloc_get_formatted_mac_string(s->mac); - if (mac) { - ESP_LOGD(TAG, "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s", s->rssi, STR_OR_BLANK(mac)); - } + if(mac) { ESP_LOGD(TAG, "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s", s->rssi, STR_OR_BLANK(mac)); } FREE_AND_NULL(mac); } break; case WIFI_EVENT_STA_WPS_ER_SUCCESS: @@ -232,9 +226,7 @@ static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, i case WIFI_EVENT_AP_STACONNECTED: { wifi_event_ap_staconnected_t* stac = (wifi_event_ap_staconnected_t*)event_data; char* mac = alloc_get_formatted_mac_string(stac->mac); - if (mac) { - ESP_LOGD(TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s", stac->aid, STR_OR_BLANK(mac)); - } + if(mac) { ESP_LOGD(TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s", stac->aid, STR_OR_BLANK(mac)); } FREE_AND_NULL(mac); } break; case WIFI_EVENT_AP_STADISCONNECTED: @@ -256,7 +248,7 @@ static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, i } break; case WIFI_EVENT_STA_DISCONNECTED: { - if (is_restarting()) { + if(is_restarting()) { ESP_LOGD(TAG, "Disconnect event ignored while restarting"); return; } @@ -266,7 +258,7 @@ static void network_wifi_event_handler(void* arg, esp_event_base_t event_base, i get_disconnect_code_desc(s->reason)); FREE_AND_NULL(bssid); - if (s->reason == WIFI_REASON_ROAMING) { + if(s->reason == WIFI_REASON_ROAMING) { ESP_LOGI(TAG, "WiFi Roaming to new access point"); } else { network_async_lost_connection((wifi_event_sta_disconnected_t*)event_data); @@ -288,7 +280,6 @@ void network_wifi_global_init() { sys_status_obj.get()->net.has_wifi = true; sys_status_obj.get()->net.wifi.scan_result = reinterpret_cast(&scan_results_aps); sntp_set_time_sync_notification_cb(time_sync_notification_cb); - } esp_netif_t* network_wifi_config_ap() { @@ -298,14 +289,12 @@ esp_netif_t* network_wifi_config_ap() { memset(&ap_config, 0x00, sizeof(ap_config)); ESP_LOGI(TAG, "Configuring Access Point."); - if (!wifi_ap_netif) { - wifi_ap_netif = esp_netif_create_default_wifi_ap(); - } - if (!is_initialized()) { + if(!wifi_ap_netif) { wifi_ap_netif = esp_netif_create_default_wifi_ap(); } + if(!is_initialized()) { ESP_LOGE(TAG, "Config not initialized"); return wifi_ap_netif; } - if (platform->has_net && platform->net.has_ap && platform->net.ap.has_ip) { + if(platform->has_net && platform->net.has_ap && platform->net.ap.has_ip) { inet_pton(AF_INET, platform->net.ap.ip.ip, (ip4_addr_t*)&info.ip); /* access point is on a static IP */ inet_pton(AF_INET, platform->net.ap.ip.gw, (ip4_addr_t*)&info.gw); /* access point is on a static IP */ inet_pton(AF_INET, platform->net.ap.ip.netmask, (ip4_addr_t*)&info.netmask); /* access point is on a static IP */ @@ -323,7 +312,7 @@ esp_netif_t* network_wifi_config_ap() { */ network_start_stop_dhcps(wifi_ap_netif, false); ESP_LOGD(TAG, "Setting tcp_ip info for access point"); - if ((err = esp_netif_set_ip_info(wifi_ap_netif, &info)) != ESP_OK) { + if((err = esp_netif_set_ip_info(wifi_ap_netif, &info)) != ESP_OK) { ESP_LOGE(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP. Error %s", esp_err_to_name(err)); return wifi_ap_netif; } @@ -337,13 +326,13 @@ esp_netif_t* network_wifi_config_ap() { const char* msg = "Setting wifi mode as WIFI_MODE_APSTA"; ESP_LOGD(TAG, "%s", msg); - if ((err = esp_wifi_set_mode(WIFI_MODE_APSTA)) != ESP_OK) { + if((err = esp_wifi_set_mode(WIFI_MODE_APSTA)) != ESP_OK) { ESP_LOGE(TAG, "%s. Error %s", msg, esp_err_to_name(err)); return wifi_ap_netif; } msg = "Setting wifi AP configuration for WIFI_IF_AP"; ESP_LOGD(TAG, "%s", msg); - if ((err = esp_wifi_set_config(WIFI_IF_AP, &ap_config)) != ESP_OK) /* stop AP DHCP server */ + if((err = esp_wifi_set_config(WIFI_IF_AP, &ap_config)) != ESP_OK) /* stop AP DHCP server */ { ESP_LOGE(TAG, "%s . Error %s", msg, esp_err_to_name(err)); return wifi_ap_netif; @@ -351,7 +340,7 @@ esp_netif_t* network_wifi_config_ap() { msg = "Setting wifi bandwidth"; ESP_LOGD(TAG, "%s (%d)", msg, DEFAULT_AP_BANDWIDTH); - if ((err = esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH)) != ESP_OK) /* stop AP + if((err = esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH)) != ESP_OK) /* stop AP DHCP server */ { ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err)); @@ -361,7 +350,7 @@ esp_netif_t* network_wifi_config_ap() { msg = "Setting wifi power save"; ESP_LOGD(TAG, "%s (%s)", msg, sys_net_config_ps_types_name(platform->net.power_save_mode)); - if ((err = esp_wifi_set_ps((wifi_ps_type_t)platform->net.power_save_mode)) != ESP_OK) /* stop AP DHCP server */ + if((err = esp_wifi_set_ps((wifi_ps_type_t)platform->net.power_save_mode)) != ESP_OK) /* stop AP DHCP server */ { ESP_LOGE(TAG, "%s failed. Error %s", msg, esp_err_to_name(err)); return wifi_ap_netif; @@ -377,40 +366,40 @@ void network_wifi_filter_unique(wifi_ap_record_t* aplist, uint16_t* aps) { first_free = NULL; - for (int i = 0; i < *aps - 1; i++) { + for(int i = 0; i < *aps - 1; i++) { wifi_ap_record_t* ap = &aplist[i]; /* skip the previously removed APs */ - if (ap->ssid[0] == 0) continue; + if(ap->ssid[0] == 0) continue; /* remove the identical SSID+authmodes */ - for (int j = i + 1; j < *aps; j++) { + for(int j = i + 1; j < *aps; j++) { wifi_ap_record_t* ap1 = &aplist[j]; - if ((strcmp((const char*)ap->ssid, (const char*)ap1->ssid) == 0) && + if((strcmp((const char*)ap->ssid, (const char*)ap1->ssid) == 0) && (ap->authmode == ap1->authmode)) { /* same SSID, different auth mode is skipped */ /* save the rssi for the display */ - if ((ap1->rssi) > (ap->rssi)) ap->rssi = ap1->rssi; + if((ap1->rssi) > (ap->rssi)) ap->rssi = ap1->rssi; /* clearing the record */ memset(ap1, 0, sizeof(wifi_ap_record_t)); } } } /* reorder the list so APs follow each other in the list */ - for (int i = 0; i < *aps; i++) { + for(int i = 0; i < *aps; i++) { wifi_ap_record_t* ap = &aplist[i]; /* skipping all that has no name */ - if (ap->ssid[0] == 0) { + if(ap->ssid[0] == 0) { /* mark the first free slot */ - if (first_free == NULL) first_free = ap; + if(first_free == NULL) first_free = ap; total_unique--; continue; } - if (first_free != NULL) { + if(first_free != NULL) { memcpy(first_free, ap, sizeof(wifi_ap_record_t)); memset(ap, 0, sizeof(wifi_ap_record_t)); /* find the next free slot */ - for (int j = 0; j < *aps; j++) { - if (aplist[j].ssid[0] == 0) { + for(int j = 0; j < *aps; j++) { + if(aplist[j].ssid[0] == 0) { first_free = &aplist[j]; break; } @@ -428,32 +417,28 @@ bool network_wifi_update_scan_list(wifi_ap_record_t* accessp_records, uint16_t c wifi_config_aps->ResetRSSI(); // clear current access point list scan_results_aps.Clear(); - if (count > 0) { + if(count > 0) { WifiList::PrintWifiSTAEntryTitle(); - ESP_LOGD(TAG, "Found %d AP(s) during scan:",count); - for (int i = 0; i < count; i++) { + ESP_LOGD(TAG, "Found %d AP(s) during scan:", count); + for(int i = 0; i < count; i++) { auto& entry = scan_results_aps.AddUpdate(&accessp_records[i]); scan_results_aps.UpdateLastSeen(&accessp_records[i]); - if (wifi_config_aps->Exists(&accessp_records[i]) && configWrapper.Lock()) { - ESP_LOGD(TAG,"AP with known password. updating last seen"); + if(wifi_config_aps->Exists(&accessp_records[i]) && configWrapper.Lock()) { + ESP_LOGD(TAG, "AP with known password. updating last seen"); changed = wifi_config_aps->Update(&accessp_records[i]) || changed; changed = wifi_config_aps->UpdateLastSeen(&accessp_records[i]) || changed; configWrapper.Unlock(); } - ESP_LOGV(TAG,"Address of entry is %p", static_cast(&entry)); + ESP_LOGV(TAG, "Address of entry is %p", static_cast(&entry)); - if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - WifiList::PrintWifiSTAEntry(entry); - } + if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { WifiList::PrintWifiSTAEntry(entry); } } } else { ESP_LOGI(TAG, "No nearby access point found"); } - if (changed) { - config_raise_changed(false); - } + if(changed) { config_raise_changed(false); } return true; } esp_err_t wifi_scan_done() { @@ -461,20 +446,20 @@ esp_err_t wifi_scan_done() { wifi_ap_record_t* accessp_records = NULL; ESP_LOGD(TAG, "Getting AP list records"); uint16_t ap_num = platform->net.max_ap_num; - if ((err = esp_wifi_scan_get_ap_num(&ap_num)) != ESP_OK) { + if((err = esp_wifi_scan_get_ap_num(&ap_num)) != ESP_OK) { ESP_LOGE(TAG, "Failed to retrieve scan results count. Error %s", esp_err_to_name(err)); return err; } - if (ap_num <= 0) { + if(ap_num <= 0) { ESP_LOGI(TAG, "No AP found during scan"); return err; } accessp_records = (wifi_ap_record_t*)malloc_init_external(sizeof(wifi_ap_record_t) * ap_num); - if (!accessp_records) { + if(!accessp_records) { ESP_LOGE(TAG, "Alloc failed for scan results"); return ESP_FAIL; } - if ((err = esp_wifi_scan_get_ap_records(&ap_num, accessp_records)) != ESP_OK) { + if((err = esp_wifi_scan_get_ap_records(&ap_num, accessp_records)) != ESP_OK) { ESP_LOGE(TAG, "Failed to retrieve scan results list. Error %s", esp_err_to_name(err)); } else { /* make sure the http server isn't trying to access the list while it gets refreshed */ @@ -482,7 +467,7 @@ esp_err_t wifi_scan_done() { /* Will remove the duplicate SSIDs from the list and update ap_num */ network_wifi_filter_unique(accessp_records, &ap_num); - if (!network_wifi_update_scan_list(accessp_records, ap_num)) { + if(!network_wifi_update_scan_list(accessp_records, ap_num)) { ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); err = ESP_FAIL; } @@ -496,13 +481,13 @@ esp_err_t network_wifi_start_scan() { wifi_scan_config_t scan_config = {.ssid = 0, .bssid = 0, .channel = 0, .show_hidden = true, .scan_type = WIFI_SCAN_TYPE_ACTIVE}; esp_err_t err = ESP_OK; ESP_LOGI(TAG, "Initiating wifi network scan"); - if (!is_wifi_up()) { + if(!is_wifi_up()) { messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot scan"); return ESP_FAIL; } /* if a scan is already in progress this message is simply ignored thanks to the * WIFI_MANAGER_SCAN_BIT uxBit */ - if ((err = esp_wifi_scan_start(&scan_config, false)) != ESP_OK) { + if((err = esp_wifi_scan_start(&scan_config, false)) != ESP_OK) { ESP_LOGW(TAG, "Unable to start scan; %s ", esp_err_to_name(err)); // set_status_message(WARNING, "Wifi Connecting. Cannot start scan."); messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Scanning failed: %s", esp_err_to_name(err)); @@ -535,40 +520,38 @@ esp_err_t network_wifi_connect(const char* ssid, const char* password) { ESP_LOGD(TAG, "network_wifi_connect"); network_wifi_set_connected(false); - if (!is_wifi_up()) { + if(!is_wifi_up()) { messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Cannot connect"); return ESP_FAIL; } - if (!ssid || !password || strlen(ssid) == 0) { + if(!ssid || !password || strlen(ssid) == 0) { ESP_LOGE(TAG, "Cannot connect wifi. wifi config is null!"); return ESP_ERR_INVALID_ARG; } wifi_mode_t wifi_mode; err = esp_wifi_get_mode(&wifi_mode); - if (err == ESP_ERR_WIFI_NOT_INIT) { + if(err == ESP_ERR_WIFI_NOT_INIT) { ESP_LOGW(TAG, "Wifi not initialized. Attempting to start sta mode"); network_wifi_start(); - } else if (err != ESP_OK) { + } else if(err != ESP_OK) { ESP_LOGE(TAG, "Could not retrieve wifi mode : %s", esp_err_to_name(err)); - } else if (wifi_mode != WIFI_MODE_STA && wifi_mode != WIFI_MODE_APSTA) { + } else if(wifi_mode != WIFI_MODE_STA && wifi_mode != WIFI_MODE_APSTA) { ESP_LOGD(TAG, "Changing wifi mode to STA"); err = network_wifi_set_sta_mode(); - if (err != ESP_OK) { + if(err != ESP_OK) { ESP_LOGE(TAG, "Could not set mode to STA. Cannot connect to SSID %s", ssid); return err; } } // copy configuration and connect strlcpy((char*)config.sta.ssid, ssid, sizeof(config.sta.ssid)); - if (password) { - strlcpy((char*)config.sta.password, password, sizeof(config.sta.password)); - } + if(password) { strlcpy((char*)config.sta.password, password, sizeof(config.sta.password)); } config.sta.scan_method = platform->net.wifi_connect_fast_scan ? WIFI_FAST_SCAN : WIFI_ALL_CHANNEL_SCAN; auto existing = wifi_config_aps->Get(&config.sta); - if (existing != nullptr) { - if (existing->channel > 0 && existing->channel <= 13) { + if(existing != nullptr) { + if(existing->channel > 0 && existing->channel <= 13) { ESP_LOGD(TAG, "Trying to connect on channel %d", existing->channel); config.sta.channel = existing->channel; } else { @@ -580,17 +563,17 @@ esp_err_t network_wifi_connect(const char* ssid, const char* password) { esp_wifi_disconnect(); config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; - if ((err = esp_wifi_set_config(WIFI_IF_STA, &config)) != ESP_OK) { + if((err = esp_wifi_set_config(WIFI_IF_STA, &config)) != ESP_OK) { ESP_LOGE(TAG, "Failed to set STA configuration. Error %s", esp_err_to_name(err)); } - if (err == ESP_OK) { + if(err == ESP_OK) { ESP_LOGI(TAG, "Wifi Connecting to %s...", ssid); - if ((err = esp_wifi_connect()) != ESP_OK) { + if((err = esp_wifi_connect()) != ESP_OK) { ESP_LOGE(TAG, "Failed to initiate wifi connection. Error %s", esp_err_to_name(err)); } else { - if (wifi_config_aps->Lock()) { + if(wifi_config_aps->Lock()) { ESP_LOGD(TAG, "Storing/updating credentials entry"); - if (wifi_config_aps->Exists(&config.sta)) { + if(wifi_config_aps->Exists(&config.sta)) { ESP_LOGD(TAG, "Existing entry. Updating it"); changed = wifi_config_aps->Update(&config.sta); } else { @@ -599,7 +582,7 @@ esp_err_t network_wifi_connect(const char* ssid, const char* password) { } auto entry = wifi_config_aps->Get(&config.sta); - if (entry != nullptr) { + if(entry != nullptr) { wifi_config_aps->UpdateLastTry(&config.sta); WifiList::PrintWifiSTAEntryTitle(); WifiList::PrintWifiSTAEntry(*entry); @@ -607,9 +590,7 @@ esp_err_t network_wifi_connect(const char* ssid, const char* password) { wifi_config_aps->Unlock(); } - if (changed) { - configWrapper.RaiseChangedAsync(); - } + if(changed) { configWrapper.RaiseChangedAsync(); } } } return err; @@ -617,7 +598,7 @@ esp_err_t network_wifi_connect(const char* ssid, const char* password) { esp_err_t network_wifi_connect_ssid(const char* ssid) { sys_net_wifi_entry* item = wifi_config_aps->Get(std::string(ssid)); - if (item != nullptr) { + if(item != nullptr) { return network_wifi_connect(item->ssid, item->password); } else { ESP_LOGE(TAG, "Attempting to connect to an unknown ssid: %s", ssid); @@ -626,10 +607,10 @@ esp_err_t network_wifi_connect_ssid(const char* ssid) { } esp_err_t network_wifi_connect_active_ssid() { sys_net_wifi_entry* connected = NULL; - if (sys_state->has_connected_sta && strlen(sys_state->connected_sta.ssid) > 0) { + if(sys_state->has_connected_sta && strlen(sys_state->connected_sta.ssid) > 0) { connected = &sys_state->connected_sta; - if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { + if(LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { ESP_LOGI(TAG, "Connecting to active access point"); WifiList::PrintWifiSTAEntryTitle(); WifiList::PrintWifiSTAEntry(sys_state->connected_sta); @@ -641,9 +622,9 @@ esp_err_t network_wifi_connect_active_ssid() { esp_err_t network_wifi_add_ssid(const char* ssid, const char* password) { bool changed = false; auto conn = wifi_config_aps->Get(ssid); - if (conn != nullptr) { + if(conn != nullptr) { ESP_LOGW(TAG, "Existing ssid %s. Updating password", ssid); - if (strcmp(conn->password, password) != 0) { + if(strcmp(conn->password, password) != 0) { strncpy(conn->password, password, sizeof(conn->password)); changed = true; } else { @@ -652,34 +633,30 @@ esp_err_t network_wifi_add_ssid(const char* ssid, const char* password) { } else { ESP_LOGI(TAG, "Adding new ssid %s with password %s to credentials", ssid, STR_OR_BLANK(password)); auto seen = scan_results_aps.Get(ssid); - if (seen) { - ESP_LOGD(TAG,"Adding with extra info from scan"); + if(seen) { + ESP_LOGD(TAG, "Adding with extra info from scan"); wifi_config_aps->AddUpdate(seen, STR_OR_BLANK(password)); changed = true; } else { - ESP_LOGD(TAG,"Adding without extra info from scan"); + ESP_LOGD(TAG, "Adding without extra info from scan"); wifi_config_aps->AddUpdate(ssid, STR_OR_BLANK(password)); changed = true; } } - if (changed) { - config_raise_changed(false); - } + if(changed) { config_raise_changed(false); } return ESP_OK; } esp_err_t network_wifi_remove_ssid(const char* ssid) { wifi_config_t config; esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error retrieving wifi config"); - } - if ((network_wifi_is_sta_mode() || network_wifi_is_ap_sta_mode()) && WifiList::GetSSID(&config.sta) == ssid) { + if(err != ESP_OK) { ESP_LOGE(TAG, "Error retrieving wifi config"); } + if((network_wifi_is_sta_mode() || network_wifi_is_ap_sta_mode()) && WifiList::GetSSID(&config.sta) == ssid) { ESP_LOGI(TAG, "Disconnecting from deleted ssid: %s", ssid); esp_wifi_disconnect(); } - if (wifi_config_aps->RemoveCredential(std::string(ssid))) { + if(wifi_config_aps->RemoveCredential(std::string(ssid))) { ESP_LOGI(TAG, "SSID %s was removed", ssid); config_raise_changed(false); } else { @@ -691,7 +668,7 @@ esp_err_t network_wifi_remove_ssid(const char* ssid) { void network_wifi_activate_strongest_ssid() { sys_state->has_connected_sta = true; auto strongest = wifi_config_aps->GetStrongestSTA(); - if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { + if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { ESP_LOGD(TAG, "Setting strongest AP as active"); WifiList::PrintWifiSTAEntryTitle(); WifiList::PrintWifiSTAEntry(strongest); @@ -703,12 +680,10 @@ void network_wifi_clear_config() { /* erase configuration */ wifi_config_aps->RemoveCredential(network_wifi_get_active_config()); esp_err_t err = ESP_OK; - if ((err = esp_wifi_disconnect()) != ESP_OK) { - ESP_LOGW(TAG, "Could not disconnect from deleted network : %s", esp_err_to_name(err)); - } + if((err = esp_wifi_disconnect()) != ESP_OK) { ESP_LOGW(TAG, "Could not disconnect from deleted network : %s", esp_err_to_name(err)); } } void print_wifi_ap_status(const wifi_sta_config_t* ap_status) { - if (ap_status == NULL) { + if(ap_status == NULL) { printf("AP status is NULL\n"); return; } @@ -740,34 +715,28 @@ void print_wifi_ap_status(const wifi_sta_config_t* ap_status) { void network_wifi_get_status() { wifi_config_t config; esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config); - if (err == ESP_OK) { + if(err == ESP_OK) { print_wifi_ap_status(&config.sta); } else { ESP_LOGE(TAG, "Error getting wifi status: %s", esp_err_to_name(err)); } - if (wifi_config_aps->GetCount() > 0 || scan_results_aps.GetCount() > 0) { - WifiList::PrintWifiSTAEntryTitle(); - } + if(wifi_config_aps->GetCount() > 0 || scan_results_aps.GetCount() > 0) { WifiList::PrintWifiSTAEntryTitle(); } ESP_LOGI(TAG, "Known access points:"); - for (int i = 0; i < wifi_config_aps->GetCount(); i++) { + for(int i = 0; i < wifi_config_aps->GetCount(); i++) { const auto entry = wifi_config_aps->GetIndex(i); - if (entry != nullptr) { - WifiList::PrintWifiSTAEntry(*entry); - } + if(entry != nullptr) { WifiList::PrintWifiSTAEntry(*entry); } } - if (scan_results_aps.GetCount() > 0) { + if(scan_results_aps.GetCount() > 0) { ESP_LOGI(TAG, "List of nearby access points"); - for (int i = 0; i < scan_results_aps.GetCount(); i++) { + for(int i = 0; i < scan_results_aps.GetCount(); i++) { const auto entry = scan_results_aps.GetIndex(i); - if (entry != nullptr) { - WifiList::PrintWifiSTAEntry(*entry); - } + if(entry != nullptr) { WifiList::PrintWifiSTAEntry(*entry); } } } } const char* get_disconnect_code_desc(uint8_t reason) { - switch (reason) { + switch(reason) { ENUM_TO_STRING(WIFI_REASON_UNSPECIFIED); ENUM_TO_STRING(WIFI_REASON_AUTH_EXPIRE); ENUM_TO_STRING(WIFI_REASON_AUTH_LEAVE); diff --git a/components/wifi-manager/network_wifi.h b/components/wifi-manager/network_wifi.h index 71e96d59..f031241e 100644 --- a/components/wifi-manager/network_wifi.h +++ b/components/wifi-manager/network_wifi.h @@ -28,8 +28,8 @@ extern "C" { #endif -esp_netif_t * network_wifi_start(); -void destroy_network_wifi(); +esp_netif_t* network_wifi_start(); +void destroy_network_wifi(); esp_err_t network_wifi_set_connected(bool connected); /** @@ -37,45 +37,43 @@ esp_err_t network_wifi_set_connected(bool connected); */ void network_wifi_register_handlers(); - /** * @brief Clear the list of access points. * @note This is not thread-safe and should be called only if network_status_lock_structure call is successful. */ void network_wifi_clear_access_points_json(); +esp_netif_t* network_wifi_config_ap(); -esp_netif_t * network_wifi_config_ap(); - -void network_wifi_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps); +void network_wifi_filter_unique(wifi_ap_record_t* aplist, uint16_t* aps); esp_err_t wifi_scan_done(); esp_err_t network_wifi_start_scan(); -esp_err_t network_wifi_load_restore(queue_message *msg); -esp_err_t network_wifi_order_connect(queue_message *msg); -esp_err_t network_wifi_disconnected(queue_message *msg); -esp_err_t network_wifi_start_ap(queue_message *msg); +esp_err_t network_wifi_load_restore(queue_message* msg); +esp_err_t network_wifi_order_connect(queue_message* msg); +esp_err_t network_wifi_disconnected(queue_message* msg); +esp_err_t network_wifi_start_ap(queue_message* msg); esp_err_t network_wifi_handle_event(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); bool is_wifi_up(); void network_wifi_get_status(); esp_err_t network_wifi_add_ssid(const char* ssid, const char* password); void network_wifi_clear_config(); void network_wifi_get_status(); -esp_netif_t *network_wifi_get_interface(); -esp_netif_t *network_wifi_get_ap_interface(); +esp_netif_t* network_wifi_get_interface(); +esp_netif_t* network_wifi_get_ap_interface(); bool network_wifi_is_ap_sta_mode(); bool network_wifi_is_sta_mode(); bool network_wifi_is_ap_mode(); bool network_wifi_sta_config_changed(); void network_wifi_global_init(); -bool network_wifi_is_known_ap(const char * ssid); -esp_err_t network_wifi_connect(const char * ssid, const char * password); -esp_err_t network_wifi_connect_ssid(const char * ssid); +bool network_wifi_is_known_ap(const char* ssid); +esp_err_t network_wifi_connect(const char* ssid, const char* password); +esp_err_t network_wifi_connect_ssid(const char* ssid); esp_err_t network_wifi_connect_active_ssid(); -esp_err_t network_wifi_remove_ssid(const char * ssid); +esp_err_t network_wifi_remove_ssid(const char* ssid); esp_err_t network_wifi_set_sta_mode(); size_t network_wifi_get_known_count(); void network_wifi_activate_strongest_ssid(); -sys_net_auth_types network_wifi_get_auth_type(const wifi_auth_mode_t mode) ; +sys_net_auth_types network_wifi_get_auth_type(const wifi_auth_mode_t mode); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/components/wifi-manager/wifi_manager_http_server.c b/components/wifi-manager/wifi_manager_http_server.c index f96a2a2f..72398901 100644 --- a/components/wifi-manager/wifi_manager_http_server.c +++ b/components/wifi-manager/wifi_manager_http_server.c @@ -39,105 +39,103 @@ static const char TAG[] = "http_server"; EXT_RAM_ATTR static httpd_handle_t _server; EXT_RAM_ATTR static int _port; -EXT_RAM_ATTR rest_server_context_t *rest_context; +EXT_RAM_ATTR rest_server_context_t* rest_context; EXT_RAM_ATTR RingbufHandle_t messaging; -httpd_handle_t http_get_server(int *port) { - if (port) *port = _port; - return _server; +httpd_handle_t http_get_server(int* port) { + if(port) *port = _port; + return _server; } -void register_common_handlers(httpd_handle_t server){ - httpd_uri_t css_get = { .uri = "/css/*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context }; - httpd_register_uri_handler(server, &css_get); - httpd_uri_t js_get = { .uri = "/js/*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context }; - httpd_register_uri_handler(server, &js_get); - httpd_uri_t icon_get = { .uri = "/icons*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context }; - httpd_register_uri_handler(server, &icon_get); - httpd_uri_t png_get = { .uri = "/favicon*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context }; - httpd_register_uri_handler(server, &png_get); +void register_common_handlers(httpd_handle_t server) { + httpd_uri_t css_get = {.uri = "/css/*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context}; + httpd_register_uri_handler(server, &css_get); + httpd_uri_t js_get = {.uri = "/js/*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context}; + httpd_register_uri_handler(server, &js_get); + httpd_uri_t icon_get = {.uri = "/icons*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context}; + httpd_register_uri_handler(server, &icon_get); + httpd_uri_t png_get = {.uri = "/favicon*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context}; + httpd_register_uri_handler(server, &png_get); } -void register_regular_handlers(httpd_handle_t server){ - httpd_uri_t root_get = { .uri = "/", .method = HTTP_GET, .handler = root_get_handler, .user_ctx = rest_context }; - httpd_register_uri_handler(server, &root_get); - // httpd_uri_t scan_get = { .uri = "/scan.bin", .method = HTTP_GET, .handler = ap_scan_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &scan_get); - // httpd_uri_t status_get = { .uri = "/status.bin", .method = HTTP_GET, .handler = status_get_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &status_get); - // httpd_uri_t messages_get = { .uri = "/messages.bin", .method = HTTP_GET, .handler = messages_get_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &messages_get); +void register_regular_handlers(httpd_handle_t server) { + httpd_uri_t root_get = {.uri = "/", .method = HTTP_GET, .handler = root_get_handler, .user_ctx = rest_context}; + httpd_register_uri_handler(server, &root_get); + // httpd_uri_t scan_get = { .uri = "/scan.bin", .method = HTTP_GET, .handler = ap_scan_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &scan_get); + // httpd_uri_t status_get = { .uri = "/status.bin", .method = HTTP_GET, .handler = status_get_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &status_get); + // httpd_uri_t messages_get = { .uri = "/messages.bin", .method = HTTP_GET, .handler = messages_get_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &messages_get); - // httpd_uri_t commands_get = { .uri = "/commands.bin", .method = HTTP_GET, .handler = console_cmd_get_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &commands_get); - // httpd_uri_t commands_post = { .uri = "/commands.bin", .method = HTTP_POST, .handler = console_cmd_post_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &commands_post); + // httpd_uri_t commands_get = { .uri = "/commands.bin", .method = HTTP_GET, .handler = console_cmd_get_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &commands_get); + // httpd_uri_t commands_post = { .uri = "/commands.bin", .method = HTTP_POST, .handler = console_cmd_post_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &commands_post); - // httpd_uri_t connect_post = { .uri = "/connect.bin", .method = HTTP_POST, .handler = connect_post_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &connect_post); + // httpd_uri_t connect_post = { .uri = "/connect.bin", .method = HTTP_POST, .handler = connect_post_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &connect_post); - // httpd_uri_t reboot_ota_post = { .uri = "/reboot_ota.bin", .method = HTTP_POST, .handler = reboot_ota_post_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &reboot_ota_post); + // httpd_uri_t reboot_ota_post = { .uri = "/reboot_ota.bin", .method = HTTP_POST, .handler = reboot_ota_post_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &reboot_ota_post); - // httpd_uri_t reboot_post = { .uri = "/reboot.bin", .method = HTTP_POST, .handler = reboot_post_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &reboot_post); + // httpd_uri_t reboot_post = { .uri = "/reboot.bin", .method = HTTP_POST, .handler = reboot_post_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &reboot_post); - // httpd_uri_t recovery_post = { .uri = "/recovery.bin", .method = HTTP_POST, .handler = recovery_post_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &recovery_post); + // httpd_uri_t recovery_post = { .uri = "/recovery.bin", .method = HTTP_POST, .handler = recovery_post_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &recovery_post); - // httpd_uri_t connect_delete = { .uri = "/connect.bin", .method = HTTP_DELETE, .handler = connect_delete_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &connect_delete); + // httpd_uri_t connect_delete = { .uri = "/connect.bin", .method = HTTP_DELETE, .handler = connect_delete_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &connect_delete); - // if(is_recovery_running){ - // httpd_uri_t flash_post = { .uri = "/flash.bin", .method = HTTP_POST, .handler = flash_post_handler, .user_ctx = rest_context }; - // httpd_register_uri_handler(server, &flash_post); - // } + // if(is_recovery_running){ + // httpd_uri_t flash_post = { .uri = "/flash.bin", .method = HTTP_POST, .handler = flash_post_handler, .user_ctx = rest_context }; + // httpd_register_uri_handler(server, &flash_post); + // } - - // from https://github.com/tripflex/wifi-captive-portal/blob/master/src/mgos_wifi_captive_portal.c - // https://unix.stackexchange.com/questions/432190/why-isnt-androids-captive-portal-detection-triggering-a-browser-window - // Known HTTP GET requests to check for Captive Portal + // from https://github.com/tripflex/wifi-captive-portal/blob/master/src/mgos_wifi_captive_portal.c + // https://unix.stackexchange.com/questions/432190/why-isnt-androids-captive-portal-detection-triggering-a-browser-window + // Known HTTP GET requests to check for Captive Portal - ///kindle-wifi/wifiredirect.html Kindle when requested with com.android.captiveportallogin - ///kindle-wifi/wifistub.html Kindle before requesting with captive portal login window (maybe for detection?) + ///kindle-wifi/wifiredirect.html Kindle when requested with com.android.captiveportallogin + ///kindle-wifi/wifistub.html Kindle before requesting with captive portal login window (maybe for detection?) + httpd_uri_t connect_redirect_1 = { + .uri = "/mobile/status.php", .method = HTTP_GET, .handler = redirect_200_ev_handler, .user_ctx = rest_context}; // Android 8.0 (Samsung s9+) + httpd_register_uri_handler(server, &connect_redirect_1); + httpd_uri_t connect_redirect_2 = { + .uri = "/generate_204", .method = HTTP_GET, .handler = redirect_200_ev_handler, .user_ctx = rest_context}; // Android + httpd_register_uri_handler(server, &connect_redirect_2); + httpd_uri_t connect_redirect_3 = {.uri = "/gen_204", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context}; // Android 9.0 + httpd_register_uri_handler(server, &connect_redirect_3); + // httpd_uri_t connect_redirect_4 = { .uri = "/ncsi.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// Windows + // httpd_register_uri_handler(server, &connect_redirect_4); + httpd_uri_t connect_redirect_5 = { + .uri = "/hotspot-detect.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context}; // iOS 8/9 + httpd_register_uri_handler(server, &connect_redirect_5); + httpd_uri_t connect_redirect_6 = { + .uri = "/library/test/success.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context}; // iOS 8/9 + httpd_register_uri_handler(server, &connect_redirect_6); + httpd_uri_t connect_redirect_7 = { + .uri = "/hotspotdetect.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context}; // iOS + httpd_register_uri_handler(server, &connect_redirect_7); + httpd_uri_t connect_redirect_8 = {.uri = "/success.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context}; // OSX + httpd_register_uri_handler(server, &connect_redirect_8); - httpd_uri_t connect_redirect_1 = { .uri = "/mobile/status.php", .method = HTTP_GET, .handler = redirect_200_ev_handler, .user_ctx = rest_context };// Android 8.0 (Samsung s9+) - httpd_register_uri_handler(server, &connect_redirect_1); - httpd_uri_t connect_redirect_2 = { .uri = "/generate_204", .method = HTTP_GET, .handler = redirect_200_ev_handler, .user_ctx = rest_context };// Android - httpd_register_uri_handler(server, &connect_redirect_2); - httpd_uri_t connect_redirect_3 = { .uri = "/gen_204", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// Android 9.0 - httpd_register_uri_handler(server, &connect_redirect_3); -// httpd_uri_t connect_redirect_4 = { .uri = "/ncsi.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// Windows -// httpd_register_uri_handler(server, &connect_redirect_4); - httpd_uri_t connect_redirect_5 = { .uri = "/hotspot-detect.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // iOS 8/9 - httpd_register_uri_handler(server, &connect_redirect_5); - httpd_uri_t connect_redirect_6 = { .uri = "/library/test/success.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// iOS 8/9 - httpd_register_uri_handler(server, &connect_redirect_6); - httpd_uri_t connect_redirect_7 = { .uri = "/hotspotdetect.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // iOS - httpd_register_uri_handler(server, &connect_redirect_7); - httpd_uri_t connect_redirect_8 = { .uri = "/success.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // OSX - httpd_register_uri_handler(server, &connect_redirect_8); - - httpd_uri_t config_post = { .uri = "/data.bin", .method = HTTP_POST, .handler = data_post_handler, .user_ctx = rest_context }; - httpd_register_uri_handler(server, &config_post); - - - - ESP_LOGD(TAG,"Registering default error handler for 404"); - httpd_register_err_handler(server, HTTPD_404_NOT_FOUND,&err_handler); + httpd_uri_t config_post = {.uri = "/data.bin", .method = HTTP_POST, .handler = data_post_handler, .user_ctx = rest_context}; + httpd_register_uri_handler(server, &config_post); + ESP_LOGD(TAG, "Registering default error handler for 404"); + httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, &err_handler); } +esp_err_t http_server_start() { -esp_err_t http_server_start() -{ - - ESP_LOGI(TAG, "Initializing HTTP Server"); - messaging = messaging_register_subscriber(10, "http_server"); - rest_context = malloc_init_external( sizeof(rest_server_context_t)); - if(rest_context==NULL){ - ESP_LOGE(TAG,"No memory for http context"); - return ESP_FAIL; + ESP_LOGI(TAG, "Initializing HTTP Server"); + messaging = messaging_register_subscriber(10, "http_server"); + rest_context = malloc_init_external(sizeof(rest_server_context_t)); + if(rest_context == NULL) { + ESP_LOGE(TAG, "No memory for http context"); + return ESP_FAIL; } strlcpy(rest_context->base_path, "/res/", sizeof(rest_context->base_path)); @@ -145,41 +143,33 @@ esp_err_t http_server_start() httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.max_uri_handlers = 30; config.max_open_sockets = 3; - config.lru_purge_enable = false; - config.backlog_conn = 1; + config.lru_purge_enable = false; + config.backlog_conn = 1; config.uri_match_fn = httpd_uri_match_wildcard; - config.task_priority = ESP_TASK_PRIO_MIN; - _port = config.server_port; + config.task_priority = ESP_TASK_PRIO_MIN; + _port = config.server_port; //todo: use the endpoint below to configure session token? // config.open_fn - esp_err_t err= httpd_start(&_server, &config); - if(err != ESP_OK){ - ESP_LOGE_LOC(TAG,"Start server failed"); + esp_err_t err = httpd_start(&_server, &config); + if(err != ESP_OK) { + ESP_LOGE_LOC(TAG, "Start server failed"); + } else { + register_common_handlers(_server); + register_regular_handlers(_server); } - else { - register_common_handlers(_server); - register_regular_handlers(_server); - } return err; } - /* Function to free context */ -void adder_free_func(void *ctx) -{ +void adder_free_func(void* ctx) { ESP_LOGD(TAG, "/adder Free Context function called"); free(ctx); } - -void stop_webserver(httpd_handle_t server) -{ +void stop_webserver(httpd_handle_t server) { // Stop the httpd server httpd_stop(server); } - - - diff --git a/main/esp_app_main.c b/main/esp_app_main.c index 335e903e..020e5359 100644 --- a/main/esp_app_main.c +++ b/main/esp_app_main.c @@ -68,7 +68,7 @@ void cb_connection_got_ip(nm_state_t new_state, int sub_state) { static ip4_addr_t ip; tcpip_adapter_ip_info_t ipInfo; network_get_ip_info(&ipInfo); - if (ip.addr && ipInfo.ip.addr != ip.addr) { + if(ip.addr && ipInfo.ip.addr != ip.addr) { config_raise_changed(false); ESP_LOGW(TAG, "IP change, need to reboot"); simple_restart(); @@ -78,13 +78,12 @@ void cb_connection_got_ip(nm_state_t new_state, int sub_state) { network_get_hostname(&hostname); mdns_init(); mdns_hostname_set(hostname); - ESP_LOGI(TAG, "Network connected and mDNS initialized with %s", hostname); messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "Network connected"); led_unpush(LED_GREEN); - if (is_recovery_running) { + if(is_recovery_running) { // when running in recovery, send a LMS discovery message // to find a running instance. This is to enable using // the plugin's proxy mode for FW download and avoid @@ -141,20 +140,18 @@ void app_main() { TRACE_INIT; ESP_LOGI(TAG, "Starting app_main"); init_spiffs(); - if (esp_log_level_get(TAG) >= ESP_LOG_DEBUG) { - listFiles("/spiffs"); - } + if(esp_log_level_get(TAG) >= ESP_LOG_DEBUG) { listFiles("/spiffs"); } - // now that the spiffs is initialized, we can load the + // now that the spiffs is initialized, we can load the // core configuration system, which is needed by // most of the other system components config_load(); - if (!platform) { + if(!platform) { ESP_LOGE(TAG, "Invalid configuration object. Cannot continue"); config_erase_config(); } - - // initialize SPI/I2C and gpios/gpio expansion modules + + // initialize SPI/I2C and gpios/gpio expansion modules // now as they may be required for hardware access by // ethernet, etc. later services_ports_init(); @@ -164,7 +161,6 @@ void app_main() { // as various subsequent init steps will post events to the queue initialize_network(); - #if defined(CONFIG_WITH_METRICS) ESP_LOGI(TAG, "Setting up metrics."); metrics_init(); @@ -173,30 +169,26 @@ void app_main() { services_init(); display_init("SqueezeESP32"); - if (platform->target && strlen(platform->target) > 0) { - target_init(platform->target); - } + if(platform->target && strlen(platform->target) > 0) { target_init(platform->target); } led_vu_init(); - if (is_recovery_running) { - if (display) { + if(is_recovery_running) { + if(display) { ESP_LOGD(TAG, "Writing to display"); GDS_ClearExt(display, true); GDS_SetFont(display, Font_line_2); GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "RECOVERY"); } - if (led_display) { - led_vu_color_yellow(LED_VU_BRIGHT); - } + if(led_display) { led_vu_color_yellow(LED_VU_BRIGHT); } } #if defined(CONFIG_WITH_METRICS) metrics_event_boot(is_recovery_running ? "recovery" : "ota"); #endif - if (!is_recovery_running) { + if(!is_recovery_running) { ESP_LOGD(TAG, "Getting audio control mapping "); - if (platform && platform->has_dev && platform->dev.root_button_profile && strlen(platform->dev.root_button_profile) > 0) { + if(platform && platform->has_dev && platform->dev.root_button_profile && strlen(platform->dev.root_button_profile) > 0) { ESP_LOGD(TAG, "Initializing audio control buttons type %s", platform->dev.root_button_profile); - if (actrls_init(platform->dev.root_button_profile) == ESP_OK) { + if(actrls_init(platform->dev.root_button_profile) == ESP_OK) { ESP_LOGD(TAG, "Done Initializing audio control buttons type %s", platform->dev.root_button_profile); } else { ESP_LOGD(TAG, "No audio control buttons"); @@ -205,9 +197,7 @@ void app_main() { } led_blink_pushed(LED_GREEN, 250, 250); - if (!is_recovery_running) { - start_squeezelite(); - } + if(!is_recovery_running) { start_squeezelite(); } console_start(); services_sleep_init(); messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "System started"); diff --git a/main/platform_esp32.h b/main/platform_esp32.h index cbe46993..6f45bf40 100644 --- a/main/platform_esp32.h +++ b/main/platform_esp32.h @@ -8,7 +8,7 @@ * https://opensource.org/licenses/MIT * */ - + #pragma once #include "esp_pthread.h" @@ -19,9 +19,5 @@ extern void console_start(); extern pthread_cond_t wifi_connect_suspend_cond; extern pthread_t wifi_connect_suspend_mutex; -typedef enum { - INFO, - WARNING, - ERROR -} message_severity_t; -extern void set_status_message(message_severity_t severity, const char * message); +typedef enum { INFO, WARNING, ERROR } message_severity_t; +extern void set_status_message(message_severity_t severity, const char* message); diff --git a/test/test_main/test_common_init.c b/test/test_main/test_common_init.c index 16f7fd49..323c6715 100644 --- a/test/test_main/test_common_init.c +++ b/test/test_main/test_common_init.c @@ -1,29 +1,22 @@ #include "unity.h" -#include "tools.h" // Assuming tools.h contains init_spiffs and listFiles +#include "tools.h" // Assuming tools.h contains init_spiffs and listFiles #include "test_common_init.h" #include "tools_spiffs_utils.h" -static const char * TAG = "test_common"; +static const char* TAG = "test_common"; -esp_err_t start_ota_return_code=ESP_OK; -void start_ota_set_return(esp_err_t mockreturn){ - start_ota_return_code = mockreturn; - -} -esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length) { - ESP_LOGI(TAG,"Received OTA Request url %s/bin buffer size: %d. returning: %s",bin_url,length,esp_err_to_name(start_ota_return_code)); +esp_err_t start_ota_return_code = ESP_OK; +void start_ota_set_return(esp_err_t mockreturn) { start_ota_return_code = mockreturn; } +esp_err_t start_ota(const char* bin_url, char* bin_buffer, uint32_t length) { + ESP_LOGI(TAG, "Received OTA Request url %s/bin buffer size: %d. returning: %s", bin_url, length, esp_err_to_name(start_ota_return_code)); return start_ota_return_code; } esp_log_level_t SetLogLevels(esp_log_level_t level) { esp_log_level_set("*", level); return esp_log_level_get(TAG); } -TEST_CASE("Raise Log Level","[test]") { - TEST_ASSERT_TRUE(SetLogLevels(ESP_LOG_DEBUG) == ESP_LOG_DEBUG ); -} -TEST_CASE("Lower Log Level","[test]") { - TEST_ASSERT_TRUE(SetLogLevels(ESP_LOG_INFO) == ESP_LOG_INFO ); -} +TEST_CASE("Raise Log Level", "[test]") { TEST_ASSERT_TRUE(SetLogLevels(ESP_LOG_DEBUG) == ESP_LOG_DEBUG); } +TEST_CASE("Lower Log Level", "[test]") { TEST_ASSERT_TRUE(SetLogLevels(ESP_LOG_INFO) == ESP_LOG_INFO); } TEST_CASE("List dir content", "[tools]") { common_test_init(); diff --git a/test/test_main/test_runner.c b/test/test_main/test_runner.c index 40cc5584..096c5c99 100644 --- a/test/test_main/test_runner.c +++ b/test/test_main/test_runner.c @@ -12,43 +12,35 @@ #include "unity.h" #include "esp_log.h" #include "test_common_init.h" -#include "tools.h" // Assuming tools.h contains init_spiffs and listFiles +#include "tools.h" // Assuming tools.h contains init_spiffs and listFiles #include "freertos/task.h" #include "network_manager.h" #include "messaging.h" #include "tools_spiffs_utils.h" #include "bootstate.h" -static const char * TAG = "test_runner"; -bool spiffs_started=false; -bool dummycond=false; +static const char* TAG = "test_runner"; +bool spiffs_started = false; +bool dummycond = false; static EXT_RAM_ATTR RingbufHandle_t messaging; - -static void print_banner(const char* text) -{ - printf("\n#### %s #####\n\n", text); -} +static void print_banner(const char* text) { printf("\n#### %s #####\n\n", text); } void common_test_init() { - if(!spiffs_started){ + if(!spiffs_started) { spiffs_started = true; init_spiffs(); listFiles(spiffs_base_path); } - - } void app_main() { esp_log_level_set("*", ESP_LOG_DEBUG); messaging_service_init(); bootstate_handle_boot(); - + init_spiffs(); - if (esp_log_level_get(TAG) >= ESP_LOG_DEBUG) { - listFiles(spiffs_base_path); - } + if(esp_log_level_get(TAG) >= ESP_LOG_DEBUG) { listFiles(spiffs_base_path); } // Start the network task at this point; this is critical // as various subsequent init steps will post events to the queue @@ -56,9 +48,8 @@ void app_main() { // also register a subscriber in case we need to check for results in tests messaging = messaging_register_subscriber(10, "test_runner"); - - /* These are the different ways of running registered tests. + /* These are the different ways of running registered tests. * In practice, only one of them is usually needed. * * UNITY_BEGIN() and UNITY_END() calls tell Unity to print a summary