Fix Back being trapped on the connecting popup (all three connect flows)
BT Inspector, BLE HID Host and Sensor Dashboard showed a "Connecting..." / "Discovering..." popup whose Back handler ignored the key, so if a connect or service discovery ran long the user was stuck until it timed out. Back on that popup now sets a cancel flag and returns to the scan list immediately; the worker thread notices the flag when its current operation finishes, drops the half-made connection and resumes scanning, and the completion handler ignores the cancelled result instead of jumping into the device/readings view. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEaD4ZeAfvWLBUxXp8G11r
This commit is contained in:
@@ -84,6 +84,7 @@ typedef struct {
|
|||||||
Sub subs[SUBS_MAX];
|
Sub subs[SUBS_MAX];
|
||||||
int sub_count;
|
int sub_count;
|
||||||
bool connected_ok;
|
bool connected_ok;
|
||||||
|
volatile bool cancel;
|
||||||
char setup_msg[48];
|
char setup_msg[48];
|
||||||
} App;
|
} App;
|
||||||
|
|
||||||
@@ -95,6 +96,8 @@ typedef struct {
|
|||||||
|
|
||||||
// ---- logging ----------------------------------------------------------------
|
// ---- logging ----------------------------------------------------------------
|
||||||
|
|
||||||
|
static App* s_app; // popup Back callback (popup view ctx isn't the App)
|
||||||
|
|
||||||
static void app_log(App* app, const char* fmt, ...) {
|
static void app_log(App* app, const char* fmt, ...) {
|
||||||
if(!app->log) return;
|
if(!app->log) return;
|
||||||
DateTime dt;
|
DateTime dt;
|
||||||
@@ -240,7 +243,13 @@ static int32_t worker_thread(void* ctx) {
|
|||||||
while(furi_message_queue_get(app->jobs, &job, FuriWaitForever) == FuriStatusOk) {
|
while(furi_message_queue_get(app->jobs, &job, FuriWaitForever) == FuriStatusOk) {
|
||||||
if(job == JobQuit) break;
|
if(job == JobQuit) break;
|
||||||
if(job == JobConnect) {
|
if(job == JobConnect) {
|
||||||
app->connected_ok = bc_connect(app->bc, &app->dev, 8000) && hid_setup(app);
|
bool ok = bc_connect(app->bc, &app->dev, 8000) && hid_setup(app);
|
||||||
|
if(app->cancel) {
|
||||||
|
if(bc_is_connected(app->bc)) bc_disconnect(app->bc);
|
||||||
|
bc_scan_start(app->bc);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
app->connected_ok = ok;
|
||||||
} else if(job == JobDisconnect) {
|
} else if(job == JobDisconnect) {
|
||||||
bc_disconnect(app->bc);
|
bc_disconnect(app->bc);
|
||||||
bc_scan_start(app->bc);
|
bc_scan_start(app->bc);
|
||||||
@@ -442,9 +451,11 @@ static uint32_t nav_mon_back(void* ctx) {
|
|||||||
return ViewScan;
|
return ViewScan;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t nav_stay_popup(void* ctx) {
|
static uint32_t nav_connecting_back(void* ctx) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
return ViewPopup;
|
s_app->cancel = true;
|
||||||
|
s_app->cur_view = ViewScan;
|
||||||
|
return ViewScan;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- events -----------------------------------------------------------------
|
// ---- events -----------------------------------------------------------------
|
||||||
@@ -508,12 +519,17 @@ static bool custom_event_cb(void* ctx, uint32_t event) {
|
|||||||
false);
|
false);
|
||||||
if(have) {
|
if(have) {
|
||||||
app_log(app, "CONNECTING %s", dev_label(&app->dev));
|
app_log(app, "CONNECTING %s", dev_label(&app->dev));
|
||||||
|
app->cancel = false;
|
||||||
show_popup(app, "Connecting...", dev_label(&app->dev), false);
|
show_popup(app, "Connecting...", dev_label(&app->dev), false);
|
||||||
furi_message_queue_put(app->jobs, &(JobType){JobConnect}, 0);
|
furi_message_queue_put(app->jobs, &(JobType){JobConnect}, 0);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case EvtNotify: on_notify(app); break;
|
case EvtNotify: on_notify(app); break;
|
||||||
case EvtJobDone:
|
case EvtJobDone:
|
||||||
|
if(app->cancel) {
|
||||||
|
app->cancel = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(app->connected_ok) {
|
if(app->connected_ok) {
|
||||||
char hdr[40];
|
char hdr[40];
|
||||||
snprintf(hdr, sizeof(hdr), "%s", dev_label(&app->dev));
|
snprintf(hdr, sizeof(hdr), "%s", dev_label(&app->dev));
|
||||||
@@ -554,6 +570,7 @@ int32_t ble_hid_host_app(void* p) {
|
|||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
App* app = malloc(sizeof(App));
|
App* app = malloc(sizeof(App));
|
||||||
memset(app, 0, sizeof(App));
|
memset(app, 0, sizeof(App));
|
||||||
|
s_app = app;
|
||||||
app->gui = furi_record_open(RECORD_GUI);
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
app->storage = furi_record_open(RECORD_STORAGE);
|
app->storage = furi_record_open(RECORD_STORAGE);
|
||||||
app->jobs = furi_message_queue_alloc(8, sizeof(JobType));
|
app->jobs = furi_message_queue_alloc(8, sizeof(JobType));
|
||||||
@@ -582,7 +599,7 @@ int32_t ble_hid_host_app(void* p) {
|
|||||||
view_dispatcher_add_view(app->vd, ViewMonitor, app->mon_view);
|
view_dispatcher_add_view(app->vd, ViewMonitor, app->mon_view);
|
||||||
|
|
||||||
app->popup = popup_alloc();
|
app->popup = popup_alloc();
|
||||||
view_set_previous_callback(popup_get_view(app->popup), nav_stay_popup);
|
view_set_previous_callback(popup_get_view(app->popup), nav_connecting_back);
|
||||||
view_dispatcher_add_view(app->vd, ViewPopup, popup_get_view(app->popup));
|
view_dispatcher_add_view(app->vd, ViewPopup, popup_get_view(app->popup));
|
||||||
|
|
||||||
app->timer = furi_timer_alloc(timer_cb, FuriTimerTypePeriodic, app);
|
app->timer = furi_timer_alloc(timer_cb, FuriTimerTypePeriodic, app);
|
||||||
|
|||||||
+23
-6
@@ -70,9 +70,12 @@ typedef struct {
|
|||||||
BcService services[BC_MAX_SERVICES];
|
BcService services[BC_MAX_SERVICES];
|
||||||
BcChar chars[BC_MAX_CHARS];
|
BcChar chars[BC_MAX_CHARS];
|
||||||
bool connected_ok;
|
bool connected_ok;
|
||||||
|
volatile bool cancel;
|
||||||
char setup_msg[40];
|
char setup_msg[40];
|
||||||
} App;
|
} App;
|
||||||
|
|
||||||
|
static App* s_app; // for the popup Back callback (popup view ctx isn't the App)
|
||||||
|
|
||||||
static const char* dev_label(const BcDevice* d) {
|
static const char* dev_label(const BcDevice* d) {
|
||||||
return d->name[0] ? d->name : "(no name)";
|
return d->name[0] ? d->name : "(no name)";
|
||||||
}
|
}
|
||||||
@@ -139,9 +142,15 @@ static int32_t worker_thread(void* ctx) {
|
|||||||
JobType job;
|
JobType job;
|
||||||
while(furi_message_queue_get(app->jobs, &job, FuriWaitForever) == FuriStatusOk) {
|
while(furi_message_queue_get(app->jobs, &job, FuriWaitForever) == FuriStatusOk) {
|
||||||
if(job == JobQuit) break;
|
if(job == JobQuit) break;
|
||||||
if(job == JobConnect)
|
if(job == JobConnect) {
|
||||||
app->connected_ok = bc_connect(app->bc, &app->dev, 8000) && sensor_setup(app);
|
bool ok = bc_connect(app->bc, &app->dev, 8000) && sensor_setup(app);
|
||||||
else if(job == JobDisconnect) {
|
if(app->cancel) { // user pressed Back while we were busy
|
||||||
|
if(bc_is_connected(app->bc)) bc_disconnect(app->bc);
|
||||||
|
bc_scan_start(app->bc);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
app->connected_ok = ok;
|
||||||
|
} else if(job == JobDisconnect) {
|
||||||
bc_disconnect(app->bc);
|
bc_disconnect(app->bc);
|
||||||
bc_scan_start(app->bc);
|
bc_scan_start(app->bc);
|
||||||
}
|
}
|
||||||
@@ -288,9 +297,11 @@ static uint32_t scan_exit(void* ctx) {
|
|||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
return VIEW_NONE;
|
return VIEW_NONE;
|
||||||
}
|
}
|
||||||
static uint32_t stay_popup(void* ctx) {
|
static uint32_t connecting_back(void* ctx) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
return ViewPopup;
|
s_app->cancel = true; // worker will drop the half-made connection
|
||||||
|
s_app->cur = ViewScan;
|
||||||
|
return ViewScan;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void popup_cb(void* ctx) {
|
static void popup_cb(void* ctx) {
|
||||||
@@ -343,6 +354,7 @@ static bool custom_cb(void* ctx, uint32_t event) {
|
|||||||
popup_set_context(app->popup, app);
|
popup_set_context(app->popup, app);
|
||||||
popup_set_header(app->popup, "Connecting...", 64, 26, AlignCenter, AlignCenter);
|
popup_set_header(app->popup, "Connecting...", 64, 26, AlignCenter, AlignCenter);
|
||||||
popup_set_text(app->popup, dev_label(&app->dev), 64, 40, AlignCenter, AlignCenter);
|
popup_set_text(app->popup, dev_label(&app->dev), 64, 40, AlignCenter, AlignCenter);
|
||||||
|
app->cancel = false;
|
||||||
app->cur = ViewPopup;
|
app->cur = ViewPopup;
|
||||||
view_dispatcher_switch_to_view(app->vd, ViewPopup);
|
view_dispatcher_switch_to_view(app->vd, ViewPopup);
|
||||||
furi_message_queue_put(app->jobs, &(JobType){JobConnect}, 0);
|
furi_message_queue_put(app->jobs, &(JobType){JobConnect}, 0);
|
||||||
@@ -350,6 +362,10 @@ static bool custom_cb(void* ctx, uint32_t event) {
|
|||||||
} break;
|
} break;
|
||||||
case EvtNotify: on_notify(app); break;
|
case EvtNotify: on_notify(app); break;
|
||||||
case EvtJobDone:
|
case EvtJobDone:
|
||||||
|
if(app->cancel) { // user already backed out to the scan list
|
||||||
|
app->cancel = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(app->connected_ok) {
|
if(app->connected_ok) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
app->readings_view, ReadingsModel * m,
|
app->readings_view, ReadingsModel * m,
|
||||||
@@ -383,6 +399,7 @@ int32_t ble_sensor_app(void* p) {
|
|||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
App* app = malloc(sizeof(App));
|
App* app = malloc(sizeof(App));
|
||||||
memset(app, 0, sizeof(App));
|
memset(app, 0, sizeof(App));
|
||||||
|
s_app = app;
|
||||||
app->gui = furi_record_open(RECORD_GUI);
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
app->jobs = furi_message_queue_alloc(8, sizeof(JobType));
|
app->jobs = furi_message_queue_alloc(8, sizeof(JobType));
|
||||||
app->notify_q = furi_message_queue_alloc(16, sizeof(NotifyMsg));
|
app->notify_q = furi_message_queue_alloc(16, sizeof(NotifyMsg));
|
||||||
@@ -410,7 +427,7 @@ int32_t ble_sensor_app(void* p) {
|
|||||||
view_dispatcher_add_view(app->vd, ViewReadings, app->readings_view);
|
view_dispatcher_add_view(app->vd, ViewReadings, app->readings_view);
|
||||||
|
|
||||||
app->popup = popup_alloc();
|
app->popup = popup_alloc();
|
||||||
view_set_previous_callback(popup_get_view(app->popup), stay_popup);
|
view_set_previous_callback(popup_get_view(app->popup), connecting_back);
|
||||||
view_dispatcher_add_view(app->vd, ViewPopup, popup_get_view(app->popup));
|
view_dispatcher_add_view(app->vd, ViewPopup, popup_get_view(app->popup));
|
||||||
|
|
||||||
app->timer = furi_timer_alloc(timer_cb, FuriTimerTypePeriodic, app);
|
app->timer = furi_timer_alloc(timer_cb, FuriTimerTypePeriodic, app);
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ typedef struct {
|
|||||||
|
|
||||||
JobType job;
|
JobType job;
|
||||||
bool job_ok;
|
bool job_ok;
|
||||||
|
volatile bool cancel;
|
||||||
FuriString* status;
|
FuriString* status;
|
||||||
FuriString* info_text;
|
FuriString* info_text;
|
||||||
} App;
|
} App;
|
||||||
@@ -853,7 +854,10 @@ static uint32_t nav_exit(void* ctx) {
|
|||||||
|
|
||||||
static uint32_t nav_stay_popup(void* ctx) {
|
static uint32_t nav_stay_popup(void* ctx) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
return ViewPopup;
|
// Back on a connect/discover popup: abort and return to the scan list.
|
||||||
|
nav_app->cancel = true;
|
||||||
|
nav_app->cur_view = ViewScan;
|
||||||
|
return ViewScan;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t nav_page_back(void* ctx) {
|
static uint32_t nav_page_back(void* ctx) {
|
||||||
@@ -916,6 +920,16 @@ static void on_tick(App* app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void on_job_done(App* app) {
|
static void on_job_done(App* app) {
|
||||||
|
if(app->cancel) { // user backed out of the connect/discover popup
|
||||||
|
app->cancel = false;
|
||||||
|
if(app->job != JobDisconnect) {
|
||||||
|
if(bc_is_connected(app->bc))
|
||||||
|
post_job(app, JobDisconnect);
|
||||||
|
else
|
||||||
|
bc_scan_start(app->bc);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch(app->job) {
|
switch(app->job) {
|
||||||
case JobConnect:
|
case JobConnect:
|
||||||
if(app->job_ok) {
|
if(app->job_ok) {
|
||||||
@@ -1038,6 +1052,7 @@ static bool custom_event_cb(void* ctx, uint32_t event) {
|
|||||||
case EvtPageCenter:
|
case EvtPageCenter:
|
||||||
if(app->page_kind == PageDetails) {
|
if(app->page_kind == PageDetails) {
|
||||||
app_log(app, "CONNECTING %s", dev_label(&app->dev));
|
app_log(app, "CONNECTING %s", dev_label(&app->dev));
|
||||||
|
app->cancel = false;
|
||||||
show_popup(app, "Connecting...", dev_label(&app->dev), false);
|
show_popup(app, "Connecting...", dev_label(&app->dev), false);
|
||||||
post_job(app, JobConnect);
|
post_job(app, JobConnect);
|
||||||
} else if(app->page_kind == PageChar) {
|
} else if(app->page_kind == PageChar) {
|
||||||
@@ -1059,6 +1074,12 @@ static bool custom_event_cb(void* ctx, uint32_t event) {
|
|||||||
case EvtJobDone: on_job_done(app); break;
|
case EvtJobDone: on_job_done(app); break;
|
||||||
case EvtNotify: on_notify(app); break;
|
case EvtNotify: on_notify(app); break;
|
||||||
case EvtPopupDone:
|
case EvtPopupDone:
|
||||||
|
if(app->cancel) {
|
||||||
|
app->cancel = false;
|
||||||
|
bc_scan_start(app->bc);
|
||||||
|
show_view(app, ViewScan);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(app->after_popup == AfterPopupServices) {
|
if(app->after_popup == AfterPopupServices) {
|
||||||
show_view(app, ViewServices);
|
show_view(app, ViewServices);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user