From 25d686fdfbc86bc65cada723c7a35ba46247b07a Mon Sep 17 00:00:00 2001 From: HaxSam Date: Fri, 1 Mar 2024 09:49:39 +0100 Subject: [PATCH] add is_connected api for expansion \w @Willy-JL --- applications/services/expansion/expansion.c | 47 ++++++++++++++++--- applications/services/expansion/expansion.h | 8 ++++ .../services/expansion/expansion_worker.c | 3 +- .../services/expansion/expansion_worker.h | 7 ++- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/applications/services/expansion/expansion.c b/applications/services/expansion/expansion.c index 5b834b48d..ef760eede 100644 --- a/applications/services/expansion/expansion.c +++ b/applications/services/expansion/expansion.c @@ -18,6 +18,7 @@ typedef enum { ExpansionStateDisabled, ExpansionStateEnabled, ExpansionStateRunning, + ExpansionStateConnectionEstablished, } ExpansionState; typedef enum { @@ -26,6 +27,7 @@ typedef enum { ExpansionMessageTypeSetListenSerial, ExpansionMessageTypeModuleConnected, ExpansionMessageTypeModuleDisconnected, + ExpansionMessageTypeConnectionEstablished, } ExpansionMessageType; typedef union { @@ -68,13 +70,21 @@ static void expansion_detect_callback(void* context) { UNUSED(status); } -static void expansion_worker_callback(void* context) { +static void expansion_worker_callback(void* context, ExpansionWorkerCallbackReason reason) { furi_assert(context); Expansion* instance = context; - ExpansionMessage message = { - .type = ExpansionMessageTypeModuleDisconnected, - .api_lock = NULL, // Not locking the API here to avoid a deadlock + ExpansionMessage message; + switch(reason) { + case ExpansionWorkerCallbackReasonExit: + message.type = ExpansionMessageTypeModuleDisconnected; + message.api_lock = NULL; // Not locking the API here to avoid a deadlock + break; + + case ExpansionWorkerCallbackReasonConnected: + message.type = ExpansionMessageTypeConnectionEstablished; + message.api_lock = api_lock_alloc_locked(); + break; }; const FuriStatus status = furi_message_queue_put(instance->queue, &message, FuriWaitForever); @@ -105,7 +115,9 @@ static void if(instance->state == ExpansionStateDisabled) { return; - } else if(instance->state == ExpansionStateRunning) { + } else if( + instance->state == ExpansionStateRunning || + instance->state == ExpansionStateConnectionEstablished) { expansion_worker_stop(instance->worker); expansion_worker_free(instance->worker); } else { @@ -122,7 +134,8 @@ static void expansion_control_handler_set_listen_serial( const ExpansionMessageData* data) { furi_check(data->serial_id < FuriHalSerialIdMax); - if(instance->state == ExpansionStateRunning) { + if(instance->state == ExpansionStateRunning || + instance->state == ExpansionStateConnectionEstablished) { expansion_worker_stop(instance->worker); expansion_worker_free(instance->worker); @@ -160,7 +173,8 @@ static void expansion_control_handler_module_disconnected( Expansion* instance, const ExpansionMessageData* data) { UNUSED(data); - if(instance->state != ExpansionStateRunning) { + if(instance->state != ExpansionStateRunning && + instance->state != ExpansionStateConnectionEstablished) { return; } @@ -170,6 +184,18 @@ static void expansion_control_handler_module_disconnected( instance->serial_id, expansion_detect_callback, instance); } +static void expansion_control_handler_module_connection_established( + Expansion* instance, + const ExpansionMessageData* data) { + UNUSED(data); + if(instance->state != ExpansionStateRunning && + instance->state != ExpansionStateConnectionEstablished) { + return; + } + + instance->state = ExpansionStateConnectionEstablished; +} + typedef void (*ExpansionControlHandler)(Expansion*, const ExpansionMessageData*); static const ExpansionControlHandler expansion_control_handlers[] = { @@ -178,6 +204,8 @@ static const ExpansionControlHandler expansion_control_handlers[] = { [ExpansionMessageTypeSetListenSerial] = expansion_control_handler_set_listen_serial, [ExpansionMessageTypeModuleConnected] = expansion_control_handler_module_connected, [ExpansionMessageTypeModuleDisconnected] = expansion_control_handler_module_disconnected, + [ExpansionMessageTypeConnectionEstablished] = + expansion_control_handler_module_connection_established, }; static int32_t expansion_control(void* context) { @@ -249,6 +277,11 @@ void expansion_disable(Expansion* instance) { api_lock_wait_unlock_and_free(message.api_lock); } +bool expansion_is_connected(Expansion* instance) { + furi_check(instance); + return instance->state == ExpansionStateConnectionEstablished; +} + void expansion_set_listen_serial(Expansion* instance, FuriHalSerialId serial_id) { furi_check(instance); furi_check(serial_id < FuriHalSerialIdMax); diff --git a/applications/services/expansion/expansion.h b/applications/services/expansion/expansion.h index e169b3c15..6643291a9 100644 --- a/applications/services/expansion/expansion.h +++ b/applications/services/expansion/expansion.h @@ -50,6 +50,14 @@ void expansion_enable(Expansion* instance); */ void expansion_disable(Expansion* instance); +/** + * @brief Check support for expansion modules if its currently connected. + * + * @param[in,out] instance pointer to the Expansion instance. + * + */ +bool expansion_is_connected(Expansion* instance); + /** * @brief Enable support for expansion modules on designated serial port. * diff --git a/applications/services/expansion/expansion_worker.c b/applications/services/expansion/expansion_worker.c index fd92063d2..4047212eb 100644 --- a/applications/services/expansion/expansion_worker.c +++ b/applications/services/expansion/expansion_worker.c @@ -223,6 +223,7 @@ static bool expansion_worker_handle_state_handshake( if(furi_hal_serial_is_baud_rate_supported(instance->serial_handle, baud_rate)) { instance->state = ExpansionWorkerStateConnected; + instance->callback(instance->cb_context, ExpansionWorkerCallbackReasonConnected); // Send response at previous baud rate if(!expansion_worker_send_status_response(instance, ExpansionFrameErrorNone)) break; furi_hal_serial_set_br(instance->serial_handle, baud_rate); @@ -351,7 +352,7 @@ static int32_t expansion_worker(void* context) { // Do not invoke worker callback on user-requested exit if((instance->exit_reason != ExpansionWorkerExitReasonUser) && (instance->callback != NULL)) { - instance->callback(instance->cb_context); + instance->callback(instance->cb_context, ExpansionWorkerCallbackReasonExit); } return 0; diff --git a/applications/services/expansion/expansion_worker.h b/applications/services/expansion/expansion_worker.h index 761f79c1d..cd1da41c8 100644 --- a/applications/services/expansion/expansion_worker.h +++ b/applications/services/expansion/expansion_worker.h @@ -17,6 +17,11 @@ */ typedef struct ExpansionWorker ExpansionWorker; +typedef enum { + ExpansionWorkerCallbackReasonExit, + ExpansionWorkerCallbackReasonConnected, +} ExpansionWorkerCallbackReason; + /** * @brief Worker callback type. * @@ -24,7 +29,7 @@ typedef struct ExpansionWorker ExpansionWorker; * * @param[in,out] context pointer to a user-defined object. */ -typedef void (*ExpansionWorkerCallback)(void* context); +typedef void (*ExpansionWorkerCallback)(void* context, ExpansionWorkerCallbackReason reason); /** * @brief Create an expansion worker instance.