Compare commits

...

14 Commits

Author SHA1 Message Date
Philippe G
9588ae9f39 amp gpio control with jack - release 2021-11-20 11:08:48 -08:00
philippe44
c0c37bd98a Update CrossBuild.yml 2021-11-18 23:07:58 -08:00
philippe44
d5a8e3a4a2 Update CrossBuild.yml 2021-11-18 23:06:16 -08:00
Philippe G
d4b0bc4edb SPIRAM cannot be used for initialized data - release 2021-11-18 18:37:18 -08:00
Philippe G
635d382d71 fully remove ctrl_fd (was uninitialized in server loop) - release 2021-11-18 12:22:48 -08:00
philippe44
5d09d4f853 Update README.md 2021-11-17 10:59:44 -08:00
Philippe G
33c4c1fb31 release 2021-11-17 10:34:06 -08:00
Philippe G
e0d76281df Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32 into master-cmake 2021-11-17 10:31:22 -08:00
Philippe G
b3e67a8571 backport typo - release 2021-11-17 10:31:19 -08:00
philippe44
1e36180f05 Update README.md 2021-11-17 10:28:57 -08:00
Philippe G
08b22504bc allow array to be used in dac_controlset - release 2021-11-17 10:24:01 -08:00
philippe44
c236044228 limit sockets used by HTTP server (#122)
seems that ctrl and msg sockets are not needed
2021-11-17 07:59:30 -05:00
Philippe G
faa9976d3d switching or losing server connection was exhausting sockets - release 2021-11-13 19:17:50 -08:00
Philippe G
1dbffe6753 no EXTRAM attribute + cosmetics - release 2021-11-13 16:43:51 -08:00
14 changed files with 106 additions and 105 deletions

View File

@@ -1,6 +1,5 @@
# This is a basic workflow to help you get started with Actions # This is a basic workflow to help you get started with Actions
name: Cross-Build name: Cross-Build
on: on:
push: push:
branches-ignore: [ master ] branches-ignore: [ master ]

View File

@@ -71,7 +71,7 @@ NB: You can use the pre-build binaries SqueezeAMP4MBFlash which has all the hard
- spdif_config: bck=33,ws=25,do=15 - spdif_config: bck=33,ws=25,do=15
### ESP32-A1S ### ESP32-A1S
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 (see below) Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 with probably two variants - these boards are a mess (see below)
The board shown above has the following IO set The board shown above has the following IO set
- amplifier: GPIO21 - amplifier: GPIO21
@@ -95,8 +95,10 @@ So a possible config would be
for AC101 for AC101
- dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32 - dac_config: model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32
for ES8388 for ES8388 (it seems that there are variants with same version number - a total mess)
- dac_config: model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,i2c=16 - dac_config: model=ES8388,bck=5,ws=25,do=26,sda=18,scl=23,i2c=16
or
- dac_config: model=ES8388,bck=27,ws=25,do=26,sda=33,scl=32,i2c=16
### T-WATCH2020 by LilyGo ### T-WATCH2020 by LilyGo
This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its dac (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters This is a fun [smartwatch](http://www.lilygo.cn/prod_view.aspx?TypeId=50036&Id=1290&FId=t3:50036:3) based on ESP32. It has a 240x240 ST7789 screen and onboard audio. Not very useful to listen to anything but it works. This is an example of a device that requires an I2C set of commands for its dac (see below). There is a build-option if you decide to rebuild everything by yourself, otherwise the I2S default option works with the following parameters
@@ -154,7 +156,7 @@ So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where t
poweron: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ], poweron: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
poweroff: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ] } poweroff: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ] }
``` ```
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. The 'val parameter can be an array [v1, v2,...] to write a serie of bytes in a single i2c burst (in that case 'mode' is ignored). **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax
NB: For specific builds (all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset NB: For specific builds (all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset

View File

@@ -1,5 +1,5 @@
idf_component_register( idf_component_register(
INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis INCLUDE_DIRS . ./inc inc/alac inc/FLAC inc/helix-aac inc/mad inc/ogg inc/opus inc/opusfile inc/resample16 inc/soxr inc/vorbis
) )
if (DEFINED AAC_DISABLE_SBR) if (DEFINED AAC_DISABLE_SBR)

View File

@@ -1,6 +1,6 @@
idf_component_register( SRC_DIRS . idf_component_register( SRC_DIRS .
INCLUDE_DIRS . INCLUDE_DIRS .
PRIV_REQUIRES tools newlib console esp_common freertos PRIV_REQUIRES tools newlib console esp_common freertos
REQUIRES nvs_flash json REQUIRES nvs_flash json
) )

View File

@@ -183,7 +183,7 @@ static bool raop_sink_start(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); ESP_ERROR_CHECK( mdns_hostname_set(hostname) );
char * sink_name_buffer= (char *)config_alloc_get(NVS_TYPE_STR,"airplay_name"); char * sink_name_buffer= (char *)config_alloc_get(NVS_TYPE_STR,"airplay_name");
if(sink_name_buffer != NULL){ if (sink_name_buffer != NULL){
memset(sink_name, 0x00, sizeof(sink_name)); memset(sink_name, 0x00, sizeof(sink_name));
strncpy(sink_name,sink_name_buffer,sizeof(sink_name)-1 ); strncpy(sink_name,sink_name_buffer,sizeof(sink_name)-1 );
free(sink_name_buffer); free(sink_name_buffer);
@@ -218,7 +218,7 @@ void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
raop_cbs.data = data_cb; raop_cbs.data = data_cb;
TimerHandle_t timer = xTimerCreate("raopStart", 5000 / portTICK_RATE_MS, pdTRUE, NULL, raop_start_handler); TimerHandle_t timer = xTimerCreate("raopStart", 5000 / portTICK_RATE_MS, pdTRUE, NULL, raop_start_handler);
xTimerStart(timer, portMAX_DELAY); xTimerStart(timer, portMAX_DELAY);
LOG_INFO( "delaying AirPlay start"); LOG_INFO( "Delaying AirPlay start");
} }
} }

View File

@@ -47,7 +47,8 @@ static EXT_RAM_ATTR struct button_s {
TimerHandle_t timer; TimerHandle_t timer;
} buttons[MAX_BUTTONS]; } buttons[MAX_BUTTONS];
static EXT_RAM_ATTR struct { // can't use EXT_RAM_ATTR for initialized structure
static struct {
int gpio, level; int gpio, level;
struct button_s *button; struct button_s *button;
} polled_gpio[] = { {36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL} }; } polled_gpio[] = { {36, -1, NULL}, {39, -1, NULL}, {-1, -1, NULL} };

View File

@@ -40,7 +40,8 @@ static EXT_RAM_ATTR struct led_s {
TimerHandle_t timer; TimerHandle_t timer;
} leds[MAX_LED]; } leds[MAX_LED];
static EXT_RAM_ATTR struct { // can't use EXT_RAM_ATTR for initialized structure
static struct {
int gpio; int gpio;
int active; int active;
int pwm; int pwm;

View File

@@ -145,7 +145,7 @@ static void monitor_callback(TimerHandle_t xTimer) {
* *
*/ */
static void jack_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) { static void jack_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGD(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed"); ESP_LOGI(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed");
if (jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED); if (jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED);
} }

View File

@@ -33,6 +33,7 @@ extern const struct adac_s dac_external;
int adac_init(char *config, int i2c_port); int adac_init(char *config, int i2c_port);
void adac_deinit(void); void adac_deinit(void);
esp_err_t adac_write(int i2c_addr, uint8_t reg, uint8_t *data, size_t count);
esp_err_t adac_write_byte(int i2c_addr, uint8_t reg, uint8_t val); esp_err_t adac_write_byte(int i2c_addr, uint8_t reg, uint8_t val);
esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val); esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val);
uint8_t adac_read_byte(int i2c_addr, uint8_t reg); uint8_t adac_read_byte(int i2c_addr, uint8_t reg);

View File

@@ -150,8 +150,7 @@ uint16_t adac_read_word(int i2c_addr, uint8_t reg) {
/**************************************************************************************** /****************************************************************************************
* *
*/ */
esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val) esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val) {
{
uint8_t data[] = { i2c_addr << 1, reg, uint8_t data[] = { i2c_addr << 1, reg,
val >> 8, val & 0xff }; val >> 8, val & 0xff };
@@ -170,3 +169,25 @@ esp_err_t adac_write_word(int i2c_addr, uint8_t reg, uint16_t val)
return ret; return ret;
} }
/****************************************************************************************
*
*/
esp_err_t adac_write(int i2c_addr, uint8_t reg, uint8_t *data, size_t count) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_write(cmd, data, count, I2C_MASTER_NACK);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 200 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "I2C write failed");
}
return ret;
}

View File

@@ -218,7 +218,6 @@ static void notify(in_addr_t ip, u16_t hport, u16_t cport) {
// close existing CLI connection and open new one // close existing CLI connection and open new one
if (cli_sock >= 0) closesocket(cli_sock); if (cli_sock >= 0) closesocket(cli_sock);
cli_sock = socket(AF_INET, SOCK_STREAM, 0);
connect_cli_socket(); connect_cli_socket();
LOG_INFO("notified server %s hport %hu cport %hu", inet_ntoa(ip), hport, cport); LOG_INFO("notified server %s hport %hu cport %hu", inet_ntoa(ip), hport, cport);

View File

@@ -20,8 +20,8 @@
static const char TAG[] = "DAC external"; static const char TAG[] = "DAC external";
static void speaker(bool active) { } static void speaker(bool active);
static void headset(bool active) { } static void headset(bool active);
static bool volume(unsigned left, unsigned right) { return false; } static bool volume(unsigned left, unsigned right) { return false; }
static void power(adac_power_e mode); static void power(adac_power_e mode);
static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config); static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config);
@@ -95,6 +95,22 @@ static void power(adac_power_e mode) {
else i2c_json_execute("poweron"); else i2c_json_execute("poweron");
} }
/****************************************************************************************
* speaker
*/
static void speaker(bool active) {
if (active) i2c_json_execute("speakeron");
else i2c_json_execute("speakeroff");
}
/****************************************************************************************
* headset
*/
static void headset(bool active) {
if (active) i2c_json_execute("headseton");
else i2c_json_execute("headsetoff");
}
/**************************************************************************************** /****************************************************************************************
* *
*/ */
@@ -104,25 +120,40 @@ bool i2c_json_execute(char *set) {
if (!json_set) return true; if (!json_set) return true;
cJSON_ArrayForEach(item, json_set) cJSON_ArrayForEach(item, json_set) {
{
cJSON *reg = cJSON_GetObjectItemCaseSensitive(item, "reg"); cJSON *reg = cJSON_GetObjectItemCaseSensitive(item, "reg");
cJSON *val = cJSON_GetObjectItemCaseSensitive(item, "val"); cJSON *val = cJSON_GetObjectItemCaseSensitive(item, "val");
cJSON *mode = cJSON_GetObjectItemCaseSensitive(item, "mode");
if (!reg || !val) continue; if (cJSON_IsArray(val)) {
cJSON *value;
uint8_t *data = malloc(cJSON_GetArraySize(val));
int count = 0;
if (!mode) { if (!data) continue;
adac_write_byte(i2c_addr, reg->valueint, val->valueint);
} else if (!strcasecmp(mode->valuestring, "or")) { cJSON_ArrayForEach(value, val) {
uint8_t data = adac_read_byte(i2c_addr,reg->valueint); data[count++] = value->valueint;
data |= (uint8_t) val->valueint; }
adac_write_byte(i2c_addr, reg->valueint, data);
} else if (!strcasecmp(mode->valuestring, "and")) { adac_write(i2c_addr, reg->valueint, data, count);
uint8_t data = adac_read_byte(i2c_addr, reg->valueint); free(data);
data &= (uint8_t) val->valueint; } else {
adac_write_byte(i2c_addr, reg->valueint, data); cJSON *mode = cJSON_GetObjectItemCaseSensitive(item, "mode");
}
if (!reg || !val) continue;
if (!mode) {
adac_write_byte(i2c_addr, reg->valueint, val->valueint);
} else if (!strcasecmp(mode->valuestring, "or")) {
uint8_t data = adac_read_byte(i2c_addr,reg->valueint);
data |= (uint8_t) val->valueint;
adac_write_byte(i2c_addr, reg->valueint, data);
} else if (!strcasecmp(mode->valuestring, "and")) {
uint8_t data = adac_read_byte(i2c_addr, reg->valueint);
data &= (uint8_t) val->valueint;
adac_write_byte(i2c_addr, reg->valueint, data);
}
}
} }
return true; return true;

View File

@@ -129,8 +129,13 @@ static bool handler(u8_t *data, int len){
jack_mutes_amp = pkt->config == 0; jack_mutes_amp = pkt->config == 0;
config_set_value(NVS_TYPE_STR, "jack_mutes_amp", jack_mutes_amp ? "y" : "n"); config_set_value(NVS_TYPE_STR, "jack_mutes_amp", jack_mutes_amp ? "y" : "n");
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false); if (jack_mutes_amp && jack_inserted_svc()) {
else adac->speaker(true); adac->speaker(false);
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, !amp_control.active);
} else {
adac->speaker(true);
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, amp_control.active);
}
} }
LOG_INFO("got AUDO %02x", pkt->config); LOG_INFO("got AUDO %02x", pkt->config);
@@ -151,13 +156,12 @@ static void jack_handler(bool inserted) {
// jack detection bounces a bit but that seems fine // jack detection bounces a bit but that seems fine
if (jack_mutes_amp) { if (jack_mutes_amp) {
LOG_INFO("switching amplifier %s", inserted ? "OFF" : "ON"); LOG_INFO("switching amplifier %s", inserted ? "OFF" : "ON");
if (inserted) adac->speaker(false); adac->speaker(!inserted);
else adac->speaker(true); if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, inserted ? !amp_control.active : amp_control.active);
} }
// activate headset // activate headset
if (inserted) adac->headset(true); adac->headset(inserted);
else adac->headset(false);
// and chain if any // and chain if any
if (jack_handler_chain) (jack_handler_chain)(inserted); if (jack_handler_chain) (jack_handler_chain)(inserted);
@@ -343,12 +347,13 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
jack_handler_chain = jack_handler_svc; jack_handler_chain = jack_handler_svc;
jack_handler_svc = jack_handler; jack_handler_svc = jack_handler;
parse_set_GPIO(set_amp_gpio);
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false); if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
else adac->speaker(true); else adac->speaker(true);
adac->headset(jack_inserted_svc()); adac->headset(jack_inserted_svc());
parse_set_GPIO(set_amp_gpio);
// create task as a FreeRTOS task but uses stack in internal RAM // create task as a FreeRTOS task but uses stack in internal RAM
{ {
@@ -455,7 +460,10 @@ static void output_thread_i2s(void *arg) {
adac->speaker(false); adac->speaker(false);
led_blink(LED_GREEN, 200, 1000); led_blink(LED_GREEN, 200, 1000);
} else if (output.state == OUTPUT_RUNNING) { } else if (output.state == OUTPUT_RUNNING) {
if (!jack_mutes_amp || !jack_inserted_svc()) adac->speaker(true); if (!jack_mutes_amp || !jack_inserted_svc()) {
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, amp_control.active);
adac->speaker(true);
}
led_on(LED_GREEN); led_on(LED_GREEN);
} }
} }
@@ -513,7 +521,6 @@ static void output_thread_i2s(void *arg) {
i2s_zero_dma_buffer(CONFIG_I2S_NUM); i2s_zero_dma_buffer(CONFIG_I2S_NUM);
i2s_start(CONFIG_I2S_NUM); i2s_start(CONFIG_I2S_NUM);
adac->power(ADAC_ON); adac->power(ADAC_ON);
if (amp_control.gpio != -1) gpio_set_level(amp_control.gpio, amp_control.active);
} }
// this does not work well as set_sample_rates resets the fifos (and it's too early) // this does not work well as set_sample_rates resets the fifos (and it's too early)

View File

@@ -76,56 +76,10 @@ static esp_err_t _httpd_server_init(struct httpd_data *hd)
return ESP_FAIL; return ESP_FAIL;
} }
int ctrl_fd = cs_create_ctrl_sock(hd->config.ctrl_port);
if (ctrl_fd < 0) {
ESP_LOGE(TAG, LOG_FMT("error in creating ctrl socket (%d)"), errno);
close(fd);
return ESP_FAIL;
}
int msg_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (msg_fd < 0) {
ESP_LOGE(TAG, LOG_FMT("error in creating msg socket (%d)"), errno);
close(fd);
close(ctrl_fd);
return ESP_FAIL;
}
hd->listen_fd = fd; hd->listen_fd = fd;
hd->ctrl_fd = ctrl_fd;
hd->msg_fd = msg_fd;
return ESP_OK; return ESP_OK;
} }
static void _httpd_process_ctrl_msg(struct httpd_data *hd)
{
struct httpd_ctrl_data msg;
int ret = recv(hd->ctrl_fd, &msg, sizeof(msg), 0);
if (ret <= 0) {
ESP_LOGW(TAG, LOG_FMT("error in recv (%d)"), errno);
return;
}
if (ret != sizeof(msg)) {
ESP_LOGW(TAG, LOG_FMT("incomplete msg"));
return;
}
switch (msg.hc_msg) {
case HTTPD_CTRL_WORK:
if (msg.hc_work) {
ESP_LOGD(TAG, LOG_FMT("work"));
(*msg.hc_work)(msg.hc_work_arg);
}
break;
case HTTPD_CTRL_SHUTDOWN:
ESP_LOGD(TAG, LOG_FMT("shutdown"));
hd->hd_td.status = THREAD_STOPPING;
break;
default:
break;
}
}
static esp_err_t _httpd_accept_conn(struct httpd_data *hd, int listen_fd) static esp_err_t _httpd_accept_conn(struct httpd_data *hd, int listen_fd)
{ {
/* If no space is available for new session, close the least recently used one */ /* If no space is available for new session, close the least recently used one */
@@ -181,13 +135,10 @@ static esp_err_t _httpd_server(struct httpd_data *hd)
* older connections will be closed) */ * older connections will be closed) */
FD_SET(hd->listen_fd, &read_set); FD_SET(hd->listen_fd, &read_set);
} }
FD_SET(hd->ctrl_fd, &read_set);
int tmp_max_fd; int maxfd;
httpd_sess_set_descriptors(hd, &read_set, &tmp_max_fd); httpd_sess_set_descriptors(hd, &read_set, &maxfd);
int maxfd = MAX(hd->listen_fd, tmp_max_fd); maxfd = MAX(hd->listen_fd, maxfd);
tmp_max_fd = maxfd;
maxfd = MAX(hd->ctrl_fd, tmp_max_fd);
ESP_LOGD(TAG, LOG_FMT("doing select maxfd+1 = %d"), maxfd + 1); ESP_LOGD(TAG, LOG_FMT("doing select maxfd+1 = %d"), maxfd + 1);
int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL); int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL);
@@ -197,16 +148,6 @@ static esp_err_t _httpd_server(struct httpd_data *hd)
return ESP_OK; return ESP_OK;
} }
/* Case0: Do we have a control message? */
if (FD_ISSET(hd->ctrl_fd, &read_set)) {
ESP_LOGD(TAG, LOG_FMT("processing ctrl message"));
_httpd_process_ctrl_msg(hd);
if (hd->hd_td.status == THREAD_STOPPING) {
ESP_LOGD(TAG, LOG_FMT("stopping thread"));
return ESP_FAIL;
}
}
/* Case1: Do we have any activity on the current data /* Case1: Do we have any activity on the current data
* sessions? */ * sessions? */
int fd = -1; int fd = -1;
@@ -259,8 +200,6 @@ static void _httpd_thread(void *arg)
} }
ESP_LOGD(TAG, LOG_FMT("web server exiting")); ESP_LOGD(TAG, LOG_FMT("web server exiting"));
close(hd->msg_fd);
cs_free_ctrl_sock(hd->ctrl_fd);
_httpd_close_all_sessions(hd); _httpd_close_all_sessions(hd);
close(hd->listen_fd); close(hd->listen_fd);
hd->hd_td.status = THREAD_STOPPED; hd->hd_td.status = THREAD_STOPPED;