1111 */
1212
1313#include "log_rpc_group.h"
14+ #include "log_backend_rpc_history.h"
1415
1516#include <logging/log_rpc.h>
1617#include <nrf_rpc/nrf_rpc_serialize.h>
1718
1819#include <nrf_rpc_cbor.h>
1920
21+ #include <zephyr/kernel.h>
2022#include <zephyr/logging/log.h>
2123#include <zephyr/logging/log_backend.h>
2224#include <zephyr/logging/log_backend_std.h>
@@ -45,6 +47,18 @@ static bool panic_mode;
4547static uint32_t log_format = LOG_OUTPUT_TEXT ;
4648static enum log_rpc_level stream_level = LOG_RPC_LEVEL_NONE ;
4749
50+ #ifdef CONFIG_LOG_BACKEND_RPC_HISTORY
51+ static enum log_rpc_level history_level = LOG_RPC_LEVEL_NONE ;
52+ static void history_transfer_task (struct k_work * work );
53+ static K_MUTEX_DEFINE (history_transfer_mtx );
54+ static uint32_t history_transfer_id ;
55+ static union log_msg_generic * history_cur_msg ;
56+ static K_WORK_DEFINE (history_transfer_work , history_transfer_task ) ;
57+ static K_THREAD_STACK_DEFINE (history_transfer_workq_stack ,
58+ CONFIG_LOG_BACKEND_RPC_HISTORY_UPLOAD_THREAD_STACK_SIZE ) ;
59+ static struct k_work_q history_transfer_workq ;
60+ #endif
61+
4862/*
4963 * Verify that Zephyr logging level can be used as the nRF RPC logging level without translation.
5064 */
@@ -341,6 +355,14 @@ static void process(const struct log_backend *const backend, union log_msg_gener
341355 */
342356 stream_message (msg );
343357 }
358+
359+ #ifdef CONFIG_LOG_BACKEND_RPC_HISTORY
360+ max_level = history_level ;
361+
362+ if (max_level != LOG_RPC_LEVEL_NONE && level <= max_level ) {
363+ log_rpc_history_push (msg_generic );
364+ }
365+ #endif
344366}
345367
346368static void panic (struct log_backend const * const backend )
@@ -354,6 +376,14 @@ static void panic(struct log_backend const *const backend)
354376static void init (struct log_backend const * const backend )
355377{
356378 ARG_UNUSED (backend );
379+
380+ #ifdef CONFIG_LOG_BACKEND_RPC_HISTORY
381+ log_rpc_history_init ();
382+ k_work_queue_init (& history_transfer_workq );
383+ k_work_queue_start (& history_transfer_workq , history_transfer_workq_stack ,
384+ K_THREAD_STACK_SIZEOF (history_transfer_workq_stack ),
385+ K_LOWEST_APPLICATION_THREAD_PRIO , NULL );
386+ #endif
357387}
358388
359389static void dropped (const struct log_backend * const backend , uint32_t cnt )
@@ -410,3 +440,114 @@ static void log_rpc_set_stream_level_handler(const struct nrf_rpc_group *group,
410440
411441NRF_RPC_CBOR_CMD_DECODER (log_rpc_group , log_rpc_set_stream_level_handler ,
412442 LOG_RPC_CMD_SET_STREAM_LEVEL , log_rpc_set_stream_level_handler , NULL );
443+
444+ #ifdef CONFIG_LOG_BACKEND_RPC_HISTORY
445+
446+ static void log_rpc_set_history_level_handler (const struct nrf_rpc_group * group ,
447+ struct nrf_rpc_cbor_ctx * ctx , void * handler_data )
448+ {
449+ enum log_rpc_level level ;
450+
451+ level = (enum log_rpc_level )nrf_rpc_decode_uint (ctx );
452+
453+ if (!nrf_rpc_decoding_done_and_check (group , ctx )) {
454+ nrf_rpc_err (- EBADMSG , NRF_RPC_ERR_SRC_RECV , group , LOG_RPC_CMD_SET_HISTORY_LEVEL ,
455+ NRF_RPC_PACKET_TYPE_CMD );
456+ return ;
457+ }
458+
459+ history_level = level ;
460+
461+ nrf_rpc_rsp_send_void (group );
462+ }
463+
464+ NRF_RPC_CBOR_CMD_DECODER (log_rpc_group , log_rpc_set_history_level_handler ,
465+ LOG_RPC_CMD_SET_HISTORY_LEVEL , log_rpc_set_history_level_handler , NULL );
466+
467+ static void history_transfer_task (struct k_work * work )
468+ {
469+ const uint32_t flags = common_output_flags | LOG_OUTPUT_FLAG_CRLF_NONE ;
470+
471+ struct nrf_rpc_cbor_ctx ctx ;
472+ bool any_msg_consumed = false;
473+ struct log_msg * msg ;
474+ size_t length ;
475+ size_t max_length ;
476+
477+ NRF_RPC_CBOR_ALLOC (& log_rpc_group , ctx , CONFIG_LOG_BACKEND_RPC_HISTORY_UPLOAD_CHUNK_SIZE );
478+
479+ k_mutex_lock (& history_transfer_mtx , K_FOREVER );
480+ nrf_rpc_encode_uint (& ctx , history_transfer_id );
481+
482+ while (true) {
483+ if (!history_cur_msg ) {
484+ history_cur_msg = log_rpc_history_pop ();
485+ }
486+
487+ if (!history_cur_msg ) {
488+ break ;
489+ }
490+
491+ msg = & history_cur_msg -> log ;
492+ length = 6 + format_message_to_buf (msg , flags , NULL , 0 );
493+ max_length = ctx .zs [0 ].payload_end - ctx .zs [0 ].payload_mut ;
494+
495+ /* Check if there is enough buffer space to fit in the current message. */
496+ if (length > max_length ) {
497+ break ;
498+ }
499+
500+ nrf_rpc_encode_uint (& ctx , log_msg_get_level (msg ));
501+
502+ if (zcbor_bstr_start_encode (ctx .zs )) {
503+ max_length = ctx .zs [0 ].payload_end - ctx .zs [0 ].payload_mut ;
504+ length = format_message_to_buf (msg , flags , ctx .zs [0 ].payload_mut ,
505+ max_length );
506+ ctx .zs [0 ].payload_mut += MIN (length , max_length );
507+ zcbor_bstr_end_encode (ctx .zs , NULL );
508+ }
509+
510+ log_rpc_history_free (history_cur_msg );
511+ history_cur_msg = NULL ;
512+ any_msg_consumed = true;
513+ }
514+
515+ /* Determine if the work should be resubmitted to continue the transfer. */
516+ if (any_msg_consumed ) {
517+ k_work_submit_to_queue (& history_transfer_workq , work );
518+ } else {
519+ log_rpc_history_free (history_cur_msg );
520+ history_cur_msg = NULL ;
521+ }
522+
523+ k_mutex_unlock (& history_transfer_mtx );
524+
525+ nrf_rpc_cbor_cmd_no_err (& log_rpc_group , LOG_RPC_CMD_PUT_HISTORY_CHUNK , & ctx ,
526+ nrf_rpc_rsp_decode_void , NULL );
527+ }
528+
529+ static void log_rpc_fetch_history_handler (const struct nrf_rpc_group * group ,
530+ struct nrf_rpc_cbor_ctx * ctx , void * handler_data )
531+ {
532+ uint32_t transfer_id ;
533+
534+ transfer_id = nrf_rpc_decode_uint (ctx );
535+
536+ if (!nrf_rpc_decoding_done_and_check (group , ctx )) {
537+ nrf_rpc_err (- EBADMSG , NRF_RPC_ERR_SRC_RECV , group , LOG_RPC_CMD_FETCH_HISTORY ,
538+ NRF_RPC_PACKET_TYPE_CMD );
539+ return ;
540+ }
541+
542+ k_mutex_lock (& history_transfer_mtx , K_FOREVER );
543+ history_transfer_id = transfer_id ;
544+ k_work_submit_to_queue (& history_transfer_workq , & history_transfer_work );
545+ k_mutex_unlock (& history_transfer_mtx );
546+
547+ nrf_rpc_rsp_send_void (group );
548+ }
549+
550+ NRF_RPC_CBOR_CMD_DECODER (log_rpc_group , log_rpc_fetch_history_handler , LOG_RPC_CMD_FETCH_HISTORY ,
551+ log_rpc_fetch_history_handler , NULL );
552+
553+ #endif
0 commit comments