fix(plip): trust real SHK, drop hook forcing #26

Merged
electron merged 1 commits from fix/plip-no-hook-forcing into main 2026-06-17 07:05:28 +00:00
4 changed files with 12 additions and 63 deletions
+8 -2
View File
@@ -18,6 +18,7 @@
#include "board_config.h"
#include "es8388.h"
#include "phone.h"
#include "slic.h"
#include <inttypes.h>
#include <math.h>
@@ -376,8 +377,13 @@ static void audio_worker_task(void *arg)
xTaskCreate(ring_task, "ring", 4096, NULL, 4, NULL);
break;
case CMD_PLAY: {
/* Gate playback on hook state: no sound if handset is on-hook. */
if (!phone_is_offhook()) {
/* Gate playback on the REAL hook line (raw SLIC SHK), not phone.c's
* debounced flag. The debounced flag lags or misses the pickup while
* the bell is ringing, so an incoming-call greeting enqueued right
* after pickup would be dropped here ("on-hook") even though the
* handset is physically up. The raw SHK reads the pickup cleanly, and
* is the single source of truth for hook state. */
if (!slic_is_offhook()) {
ESP_LOGI(TAG, "play ignored: on-hook (handset down)");
break;
}
+4 -25
View File
@@ -140,9 +140,9 @@ static esp_err_t handle_status(httpd_req_t *req)
if (sta) esp_netif_get_ip_info(sta, &ip_info);
/* Report REAL state (this used to hardcode playing/off_hook to false, which
* was badly misleading during bring-up). off_hook = firmware view
* (phone_is_offhook, incl. debug override); shk = raw SLIC line (the actual
* analog hook — audio only routes to the handset when this is off-hook). */
* was badly misleading during bring-up). off_hook = firmware debounced view
* (phone_is_offhook); shk = raw SLIC line, the single source of truth that
* gates audio playback — sound routes to the handset only when shk is true. */
snprintf(buf, sizeof(buf),
"{\"board\":\"plip\",\"ip\":\"" IPSTR "\",\"playing\":%s,"
"\"off_hook\":%s,\"shk\":%s}",
@@ -600,22 +600,6 @@ static esp_err_t handle_debug_dacvol(httpd_req_t *req)
return send_json(req, "200 OK", resp);
}
/* ── GET /debug/offhook?on=1 (force hook state, bypass flaky contact) ───────── */
static esp_err_t handle_debug_offhook(httpd_req_t *req)
{
char query[24] = {0};
httpd_req_get_url_query_str(req, query, sizeof(query));
char on[4] = {0};
int v = 1; /* default: force off-hook */
if (httpd_query_key_value(query, "on", on, sizeof(on)) == ESP_OK) v = atoi(on);
phone_force_offhook(v != 0);
char resp[64];
snprintf(resp, sizeof(resp), "{\"ok\":true,\"forced_offhook\":%s}", v ? "true" : "false");
ESP_LOGI(TAG, "debug/offhook: forced %s", v ? "off-hook" : "on-hook");
return send_json(req, "200 OK", resp);
}
/* ── GET /debug/getfile?path=/x.wav (read a SPIFFS file back for diagnosis) ── */
static esp_err_t handle_debug_getfile(httpd_req_t *req)
@@ -772,7 +756,7 @@ esp_err_t net_init(void)
/* Start HTTP server. */
httpd_config_t hcfg = HTTPD_DEFAULT_CONFIG();
hcfg.server_port = 80;
hcfg.max_uri_handlers = 17;
hcfg.max_uri_handlers = 16;
hcfg.stack_size = 8192;
esp_err_t ret = httpd_start(&s_httpd, &hcfg);
@@ -821,10 +805,6 @@ esp_err_t net_init(void)
.uri = "/debug/dacvol", .method = HTTP_GET,
.handler = handle_debug_dacvol, .user_ctx = NULL,
};
static const httpd_uri_t uri_debug_offhook = {
.uri = "/debug/offhook", .method = HTTP_GET,
.handler = handle_debug_offhook, .user_ctx = NULL,
};
static const httpd_uri_t uri_debug_ring = {
.uri = "/debug/ring", .method = HTTP_GET,
.handler = handle_debug_ring, .user_ctx = NULL,
@@ -855,7 +835,6 @@ esp_err_t net_init(void)
httpd_register_uri_handler(s_httpd, &uri_debug_vol);
httpd_register_uri_handler(s_httpd, &uri_debug_getfile);
httpd_register_uri_handler(s_httpd, &uri_debug_dacvol);
httpd_register_uri_handler(s_httpd, &uri_debug_offhook);
httpd_register_uri_handler(s_httpd, &uri_debug_ring);
httpd_register_uri_handler(s_httpd, &uri_debug_ringstop);
httpd_register_uri_handler(s_httpd, &uri_debug_slic);
-31
View File
@@ -60,9 +60,6 @@
static volatile bool s_edge_pending = false;
static volatile bool s_ringing = false;
static volatile bool s_offhook = false; /* true = handset picked up */
static volatile bool s_hook_override = false; /* when true, ignore the physical hook
* and hold s_offhook at the forced value
* (debug: decouple from a flaky contact) */
/* IRAM_ATTR: ISR must live in IRAM on original ESP32. */
static void IRAM_ATTR on_hook_isr(void *arg)
@@ -163,15 +160,6 @@ static void phone_task(void *arg)
#endif
for (;;) {
/* Debug override: hold s_offhook at the forced value, ignore the
* physical hook entirely (decouples the voice loop from a flaky
* cradle contact). Set via phone_force_offhook() / GET /debug/offhook. */
if (s_hook_override) {
s_edge_pending = false;
resync_ms = 0;
vTaskDelay(pdMS_TO_TICKS(20));
continue;
}
if (s_edge_pending) {
s_edge_pending = false;
@@ -358,22 +346,3 @@ bool phone_is_offhook(void)
{
return s_offhook;
}
void phone_force_offhook(bool off)
{
/* Debug: override the physical hook. off=true → simulate pickup (DIALTONE),
* off=false → simulate hangup (IDLE). Stays in effect until reboot. */
s_hook_override = true;
if (off == s_offhook) {
ESP_LOGI(TAG, "force_offhook: already %s (override on)", off ? "off-hook" : "on-hook");
return;
}
s_offhook = off;
ESP_LOGI(TAG, "force_offhook: %s (override)", off ? "off-hook" : "on-hook");
audio_pa_set(off);
if (!off) {
audio_stop();
phone_ring_stop();
}
report_offhook(off);
}
-5
View File
@@ -31,11 +31,6 @@ void phone_ring_stop(void);
* Safe to call from any task; backed by a volatile flag updated in phone_task. */
bool phone_is_offhook(void);
/* Debug: force the hook state, overriding the physical contact until reboot.
* off=true simulates pickup (→ DIALTONE), off=false simulates hangup (→ IDLE).
* Lets the voice loop be validated independently of a flaky cradle contact. */
void phone_force_offhook(bool off);
#ifdef __cplusplus
}
#endif