Procházet zdrojové kódy

Add protobuf versioning (#954)

* Add protobuf versioning
* Add protobuf version unit test
* Change pb version providing
* Remove redundant 'call'
Albert Kharisov před 4 roky
rodič
revize
a0c16e8a19

+ 2 - 2
applications/rpc/rpc_app.c

@@ -4,7 +4,7 @@
 #include <furi.h>
 #include <loader/loader.h>
 
-void rpc_system_app_start_process(const PB_Main* request, void* context) {
+static void rpc_system_app_start_process(const PB_Main* request, void* context) {
     Rpc* rpc = context;
     furi_assert(rpc);
     furi_assert(request);
@@ -36,7 +36,7 @@ void rpc_system_app_start_process(const PB_Main* request, void* context) {
     rpc_send_and_release_empty(rpc, request->command_id, result);
 }
 
-void rpc_system_app_lock_status_process(const PB_Main* request, void* context) {
+static void rpc_system_app_lock_status_process(const PB_Main* request, void* context) {
     Rpc* rpc = context;
     furi_assert(rpc);
     furi_assert(request);

+ 10 - 8
applications/rpc/rpc_gui.c

@@ -13,7 +13,8 @@ typedef struct {
     bool virtual_display_not_empty;
 } RpcGuiSystem;
 
-void rpc_system_gui_screen_stream_frame_callback(uint8_t* data, size_t size, void* context) {
+static void
+    rpc_system_gui_screen_stream_frame_callback(uint8_t* data, size_t size, void* context) {
     furi_assert(data);
     furi_assert(size == 1024);
     furi_assert(context);
@@ -35,7 +36,7 @@ void rpc_system_gui_screen_stream_frame_callback(uint8_t* data, size_t size, voi
     free(frame);
 }
 
-void rpc_system_gui_start_screen_stream_process(const PB_Main* request, void* context) {
+static void rpc_system_gui_start_screen_stream_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(context);
     RpcGuiSystem* rpc_gui = context;
@@ -46,7 +47,7 @@ void rpc_system_gui_start_screen_stream_process(const PB_Main* request, void* co
         rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
 }
 
-void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* context) {
+static void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(context);
     RpcGuiSystem* rpc_gui = context;
@@ -56,7 +57,8 @@ void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* con
     rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
 }
 
-void rpc_system_gui_send_input_event_request_process(const PB_Main* request, void* context) {
+static void
+    rpc_system_gui_send_input_event_request_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_gui_send_input_event_request_tag);
     furi_assert(context);
@@ -141,7 +143,7 @@ static void rpc_system_gui_virtual_display_render_callback(Canvas* canvas, void*
     canvas_draw_xbm(canvas, 0, 0, canvas->width, canvas->height, rpc_gui->virtual_display_buffer);
 }
 
-void rpc_system_gui_start_virtual_display_process(const PB_Main* request, void* context) {
+static void rpc_system_gui_start_virtual_display_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(context);
     RpcGuiSystem* rpc_gui = context;
@@ -179,7 +181,7 @@ void rpc_system_gui_start_virtual_display_process(const PB_Main* request, void*
     rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
 }
 
-void rpc_system_gui_stop_virtual_display_process(const PB_Main* request, void* context) {
+static void rpc_system_gui_stop_virtual_display_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(context);
     RpcGuiSystem* rpc_gui = context;
@@ -199,7 +201,7 @@ void rpc_system_gui_stop_virtual_display_process(const PB_Main* request, void* c
     rpc_send_and_release_empty(rpc_gui->rpc, request->command_id, PB_CommandStatus_OK);
 }
 
-void rpc_system_gui_virtual_display_frame_process(const PB_Main* request, void* context) {
+static void rpc_system_gui_virtual_display_frame_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(context);
     RpcGuiSystem* rpc_gui = context;
@@ -268,4 +270,4 @@ void rpc_system_gui_free(void* ctx) {
     gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
     furi_record_close("gui");
     free(rpc_gui);
-}
+}

+ 38 - 11
applications/rpc/rpc_system.c

@@ -1,11 +1,12 @@
-#include "flipper.pb.h"
-#include "rpc_i.h"
-
+#include <flipper.pb.h>
 #include <furi_hal.h>
 #include <power/power_service/power.h>
 #include <notification/notification_messages.h>
+#include <protobuf_version.h>
 
-void rpc_system_system_ping_process(const PB_Main* msg_request, void* context) {
+#include "rpc_i.h"
+
+static void rpc_system_system_ping_process(const PB_Main* msg_request, void* context) {
     furi_assert(msg_request);
     furi_assert(msg_request->which_content == PB_Main_system_ping_request_tag);
     furi_assert(context);
@@ -34,7 +35,7 @@ void rpc_system_system_ping_process(const PB_Main* msg_request, void* context) {
     rpc_send_and_release(rpc, &msg_response);
 }
 
-void rpc_system_system_reboot_process(const PB_Main* request, void* context) {
+static void rpc_system_system_reboot_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_reboot_request_tag);
     furi_assert(context);
@@ -57,7 +58,7 @@ typedef struct {
     PB_Main* response;
 } RpcSystemSystemDeviceInfoContext;
 
-void rpc_system_system_device_info_callback(
+static void rpc_system_system_device_info_callback(
     const char* key,
     const char* value,
     bool last,
@@ -77,7 +78,7 @@ void rpc_system_system_device_info_callback(
     rpc_send_and_release(ctx->rpc, ctx->response);
 }
 
-void rpc_system_system_device_info_process(const PB_Main* request, void* context) {
+static void rpc_system_system_device_info_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_device_info_request_tag);
     furi_assert(context);
@@ -98,7 +99,7 @@ void rpc_system_system_device_info_process(const PB_Main* request, void* context
     free(response);
 }
 
-void rpc_system_system_get_datetime_process(const PB_Main* request, void* context) {
+static void rpc_system_system_get_datetime_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_get_datetime_request_tag);
     furi_assert(context);
@@ -121,9 +122,10 @@ void rpc_system_system_get_datetime_process(const PB_Main* request, void* contex
     response->content.system_get_datetime_response.datetime.weekday = datetime.weekday;
 
     rpc_send_and_release(rpc, response);
+    free(response);
 }
 
-void rpc_system_system_set_datetime_process(const PB_Main* request, void* context) {
+static void rpc_system_system_set_datetime_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_set_datetime_request_tag);
     furi_assert(context);
@@ -148,7 +150,7 @@ void rpc_system_system_set_datetime_process(const PB_Main* request, void* contex
     rpc_send_and_release_empty(rpc, request->command_id, PB_CommandStatus_OK);
 }
 
-void rpc_system_system_factory_reset_process(const PB_Main* request, void* context) {
+static void rpc_system_system_factory_reset_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_factory_reset_request_tag);
     furi_assert(context);
@@ -157,7 +159,8 @@ void rpc_system_system_factory_reset_process(const PB_Main* request, void* conte
     power_reboot(PowerBootModeNormal);
 }
 
-void rpc_system_system_play_audiovisual_alert_process(const PB_Main* request, void* context) {
+static void
+    rpc_system_system_play_audiovisual_alert_process(const PB_Main* request, void* context) {
     furi_assert(request);
     furi_assert(request->which_content == PB_Main_system_play_audiovisual_alert_request_tag);
     furi_assert(context);
@@ -170,6 +173,27 @@ void rpc_system_system_play_audiovisual_alert_process(const PB_Main* request, vo
     rpc_send_and_release_empty(rpc, request->command_id, PB_CommandStatus_OK);
 }
 
+static void rpc_system_system_protobuf_version_process(const PB_Main* request, void* context) {
+    furi_assert(request);
+    furi_assert(request->which_content == PB_Main_system_protobuf_version_request_tag);
+    furi_assert(context);
+
+    Rpc* rpc = context;
+
+    PB_Main* response = furi_alloc(sizeof(PB_Main));
+    response->command_id = request->command_id;
+    response->has_next = false;
+    response->command_status = PB_CommandStatus_OK;
+    response->which_content = PB_Main_system_protobuf_version_response_tag;
+    /* build error here means something wrong with tags in
+     * local repo https://github.com/flipperdevices/flipperzero-protobuf */
+    response->content.system_protobuf_version_response.major = PROTOBUF_MAJOR_VERSION;
+    response->content.system_protobuf_version_response.minor = PROTOBUF_MINOR_VERSION;
+
+    rpc_send_and_release(rpc, response);
+    free(response);
+}
+
 void* rpc_system_system_alloc(Rpc* rpc) {
     RpcHandler rpc_handler = {
         .message_handler = NULL,
@@ -198,5 +222,8 @@ void* rpc_system_system_alloc(Rpc* rpc) {
     rpc_handler.message_handler = rpc_system_system_play_audiovisual_alert_process;
     rpc_add_handler(rpc, PB_Main_system_play_audiovisual_alert_request_tag, &rpc_handler);
 
+    rpc_handler.message_handler = rpc_system_system_protobuf_version_process;
+    rpc_add_handler(rpc, PB_Main_system_protobuf_version_request_tag, &rpc_handler);
+
     return NULL;
 }

+ 37 - 0
applications/tests/rpc/rpc_test.c

@@ -17,6 +17,7 @@
 #include <lib/toolbox/md5.h>
 #include <cli/cli.h>
 #include <loader/loader.h>
+#include <protobuf_version.h>
 
 LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
 #define M_OPL_MsgList_t() LIST_OPLIST(MsgList)
@@ -424,6 +425,15 @@ static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
         mu_check(!strcmp(result_md5sum, expected_md5sum));
         break;
     }
+    case PB_Main_system_protobuf_version_response_tag: {
+        uint32_t major_version_expected = expected->content.system_protobuf_version_response.major;
+        uint32_t minor_version_expected = expected->content.system_protobuf_version_response.minor;
+        uint32_t major_version_result = result->content.system_protobuf_version_response.major;
+        uint32_t minor_version_result = result->content.system_protobuf_version_response.minor;
+        mu_check(major_version_expected == major_version_result);
+        mu_check(minor_version_expected == minor_version_result);
+        break;
+    }
     default:
         furi_assert(0);
         break;
@@ -1286,6 +1296,32 @@ MU_TEST(test_ping) {
     test_rpc_free_msg_list(expected_msg_list);
 }
 
+MU_TEST(test_system_protobuf_version) {
+    MsgList_t expected_msg_list;
+    MsgList_init(expected_msg_list);
+
+    PB_Main request;
+    request.command_id = ++command_id;
+    request.command_status = PB_CommandStatus_OK;
+    request.cb_content.funcs.decode = NULL;
+    request.has_next = false;
+    request.which_content = PB_Main_system_protobuf_version_request_tag;
+
+    PB_Main* response = MsgList_push_new(expected_msg_list);
+    response->command_id = command_id;
+    response->command_status = PB_CommandStatus_OK;
+    response->cb_content.funcs.encode = NULL;
+    response->has_next = false;
+    response->which_content = PB_Main_system_protobuf_version_response_tag;
+    response->content.system_protobuf_version_response.major = PROTOBUF_MAJOR_VERSION;
+    response->content.system_protobuf_version_response.minor = PROTOBUF_MINOR_VERSION;
+
+    test_rpc_encode_and_feed_one(&request);
+    test_rpc_decode_and_compare(expected_msg_list);
+
+    test_rpc_free_msg_list(expected_msg_list);
+}
+
 // TODO: 1) test for rubbish data
 //       2) test for unexpected end of packet
 //       3) test for one push of several packets
@@ -1295,6 +1331,7 @@ MU_TEST_SUITE(test_rpc_system) {
     MU_SUITE_CONFIGURE(&test_rpc_setup, &test_rpc_teardown);
 
     MU_RUN_TEST(test_ping);
+    MU_RUN_TEST(test_system_protobuf_version);
 }
 
 MU_TEST_SUITE(test_rpc_storage) {

+ 1 - 4
assets/Makefile

@@ -15,14 +15,11 @@ icons: $(ASSETS)
 $(PROTOBUF) &: $(PROTOBUF_SOURCES) $(PROTOBUF_COMPILER)
 	@echo "\tPROTOBUF\t" $(PROTOBUF_FILENAMES)
 	@$(PROTOBUF_COMPILER) -q -I$(PROTOBUF_SOURCE_DIR) -D$(PROTOBUF_COMPILED_DIR) $(PROTOBUF_SOURCES)
+	@printf "#pragma once\n#define PROTOBUF_MAJOR_VERSION $(PROTOBUF_MAJOR_VERSION)\n#define PROTOBUF_MINOR_VERSION $(PROTOBUF_MINOR_VERSION)\n" > $(PROTOBUF_COMPILED_DIR)/protobuf_version.h
 
 .PHONY: protobuf
 protobuf: $(PROTOBUF)
 
-$(PROTOBUF_FILE_ANIMATIONS): $(PROTOBUF_SOURCES_FILE_ANIMATIONS) $(PROTOBUF_COMPILER)
-	@echo "\tFILE ANIMATIONS\t" $(PROTOBUF_FILE_ANIMATIONS_FILENAMES)
-	@$(PROTOBUF_COMPILER) -q -I$(PROTOBUF_FILE_ANIMATIONS_SOURCE_DIR) -D$(PROTOBUF_FILE_ANIMATIONS_COMPILED_DIR) $(PROTOBUF_FILE_ANIMATIONS_SOURCES)
-
 $(DOLPHIN_OUTPUT_DIR): $(DOLPHIN_SOURCE_DIR)
 	@echo "\tDOLPHIN"
 	@$(ASSETS_COMPILLER) dolphin "$(DOLPHIN_SOURCE_DIR)" "$(DOLPHIN_OUTPUT_DIR)"

+ 7 - 1
assets/assets.mk

@@ -14,7 +14,13 @@ PROTOBUF_COMPILER		:= $(PROJECT_ROOT)/lib/nanopb/generator/nanopb_generator.py
 PROTOBUF_COMPILED_DIR	:= $(ASSETS_COMPILED_DIR)
 PROTOBUF_SOURCES		:= $(shell find $(PROTOBUF_SOURCE_DIR) -type f -iname '*.proto')
 PROTOBUF_FILENAMES		:= $(notdir $(addsuffix .pb.c,$(basename $(PROTOBUF_SOURCES))))
-PROTOBUF				:= $(addprefix $(PROTOBUF_COMPILED_DIR)/,$(PROTOBUF_FILENAMES))
+PROTOBUF				:= $(addprefix $(PROTOBUF_COMPILED_DIR)/,$(PROTOBUF_FILENAMES)) $(PROTOBUF_COMPILED_DIR)/protobuf_version.h
+PROTOBUF_VERSION		:= $(shell git -C $(PROTOBUF_SOURCE_DIR) fetch --tags 2>/dev/null && git -C $(PROTOBUF_SOURCE_DIR) describe --tags --abbrev=0 2>/dev/null || echo 'unknown')
+PROTOBUF_MAJOR_VERSION	:= $(word 1,$(subst ., ,$(PROTOBUF_VERSION)))
+PROTOBUF_MINOR_VERSION	:= $(word 2,$(subst ., ,$(PROTOBUF_VERSION)))
+$(if $(PROTOBUF_MAJOR_VERSION),,$(error "Protobuf major version is not specified, $$PROTOBUF_VERSION=$(PROTOBUF_VERSION), please perform git fetch in assets/protobuf directory"))
+$(if $(PROTOBUF_MINOR_VERSION),,$(error "Protobuf minor version is not specified, $$PROTOBUF_VERSION=$(PROTOBUF_VERSION), please perform git fetch in assets/protobuf directory"))
+
 PROTOBUF_CFLAGS			+= -DPB_ENABLE_MALLOC
 
 CFLAGS				+= -I$(ASSETS_COMPILED_DIR) $(PROTOBUF_CFLAGS)

+ 9 - 1
assets/compiled/flipper.pb.h

@@ -96,6 +96,8 @@ typedef struct _PB_Main {
         PB_System_GetDateTimeResponse system_get_datetime_response;
         PB_System_SetDateTimeRequest system_set_datetime_request;
         PB_System_PlayAudiovisualAlertRequest system_play_audiovisual_alert_request;
+        PB_System_ProtobufVersionRequest system_protobuf_version_request;
+        PB_System_ProtobufVersionResponse system_protobuf_version_response;
     } content; 
 } PB_Main;
 
@@ -157,6 +159,8 @@ extern "C" {
 #define PB_Main_system_get_datetime_response_tag 36
 #define PB_Main_system_set_datetime_request_tag  37
 #define PB_Main_system_play_audiovisual_alert_request_tag 38
+#define PB_Main_system_protobuf_version_request_tag 39
+#define PB_Main_system_protobuf_version_response_tag 40
 
 /* Struct field encoding specification for nanopb */
 #define PB_Empty_FIELDLIST(X, a) \
@@ -207,7 +211,9 @@ X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_factory_reset_request,content
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_get_datetime_request,content.system_get_datetime_request),  35) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_get_datetime_response,content.system_get_datetime_response),  36) \
 X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_set_datetime_request,content.system_set_datetime_request),  37) \
-X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_play_audiovisual_alert_request,content.system_play_audiovisual_alert_request),  38)
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_play_audiovisual_alert_request,content.system_play_audiovisual_alert_request),  38) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_request,content.system_protobuf_version_request),  39) \
+X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_protobuf_version_response,content.system_protobuf_version_response),  40)
 #define PB_Main_CALLBACK NULL
 #define PB_Main_DEFAULT NULL
 #define PB_Main_content_empty_MSGTYPE PB_Empty
@@ -245,6 +251,8 @@ X(a, STATIC,   ONEOF,    MSG_W_CB, (content,system_play_audiovisual_alert_reques
 #define PB_Main_content_system_get_datetime_response_MSGTYPE PB_System_GetDateTimeResponse
 #define PB_Main_content_system_set_datetime_request_MSGTYPE PB_System_SetDateTimeRequest
 #define PB_Main_content_system_play_audiovisual_alert_request_MSGTYPE PB_System_PlayAudiovisualAlertRequest
+#define PB_Main_content_system_protobuf_version_request_MSGTYPE PB_System_ProtobufVersionRequest
+#define PB_Main_content_system_protobuf_version_response_MSGTYPE PB_System_ProtobufVersionResponse
 
 extern const pb_msgdesc_t PB_Empty_msg;
 extern const pb_msgdesc_t PB_StopSession_msg;

+ 3 - 0
assets/compiled/protobuf_version.h

@@ -0,0 +1,3 @@
+#pragma once
+#define PROTOBUF_MAJOR_VERSION 0
+#define PROTOBUF_MINOR_VERSION 1

+ 6 - 0
assets/compiled/system.pb.c

@@ -39,5 +39,11 @@ PB_BIND(PB_System_DateTime, PB_System_DateTime, AUTO)
 PB_BIND(PB_System_PlayAudiovisualAlertRequest, PB_System_PlayAudiovisualAlertRequest, AUTO)
 
 
+PB_BIND(PB_System_ProtobufVersionRequest, PB_System_ProtobufVersionRequest, AUTO)
+
+
+PB_BIND(PB_System_ProtobufVersionResponse, PB_System_ProtobufVersionResponse, AUTO)
+
+
 
 

+ 32 - 0
assets/compiled/system.pb.h

@@ -45,6 +45,10 @@ typedef struct _PB_System_PlayAudiovisualAlertRequest {
     char dummy_field;
 } PB_System_PlayAudiovisualAlertRequest;
 
+typedef struct _PB_System_ProtobufVersionRequest { 
+    char dummy_field;
+} PB_System_ProtobufVersionRequest;
+
 typedef struct _PB_System_DateTime { 
     /* Time */
     uint8_t hour; /* *< Hour in 24H format: 0-23 */
@@ -57,6 +61,11 @@ typedef struct _PB_System_DateTime {
     uint8_t weekday; /* *< Current weekday: 1-7 */
 } PB_System_DateTime;
 
+typedef struct _PB_System_ProtobufVersionResponse { 
+    uint32_t major; 
+    uint32_t minor; 
+} PB_System_ProtobufVersionResponse;
+
 typedef struct _PB_System_RebootRequest { 
     PB_System_RebootRequest_RebootMode mode; 
 } PB_System_RebootRequest;
@@ -94,6 +103,8 @@ extern "C" {
 #define PB_System_SetDateTimeRequest_init_default {false, PB_System_DateTime_init_default}
 #define PB_System_DateTime_init_default          {0, 0, 0, 0, 0, 0, 0}
 #define PB_System_PlayAudiovisualAlertRequest_init_default {0}
+#define PB_System_ProtobufVersionRequest_init_default {0}
+#define PB_System_ProtobufVersionResponse_init_default {0, 0}
 #define PB_System_PingRequest_init_zero          {NULL}
 #define PB_System_PingResponse_init_zero         {NULL}
 #define PB_System_RebootRequest_init_zero        {_PB_System_RebootRequest_RebootMode_MIN}
@@ -105,6 +116,8 @@ extern "C" {
 #define PB_System_SetDateTimeRequest_init_zero   {false, PB_System_DateTime_init_zero}
 #define PB_System_DateTime_init_zero             {0, 0, 0, 0, 0, 0, 0}
 #define PB_System_PlayAudiovisualAlertRequest_init_zero {0}
+#define PB_System_ProtobufVersionRequest_init_zero {0}
+#define PB_System_ProtobufVersionResponse_init_zero {0, 0}
 
 /* Field tags (for use in manual encoding/decoding) */
 #define PB_System_DeviceInfoResponse_key_tag     1
@@ -118,6 +131,8 @@ extern "C" {
 #define PB_System_DateTime_month_tag             5
 #define PB_System_DateTime_year_tag              6
 #define PB_System_DateTime_weekday_tag           7
+#define PB_System_ProtobufVersionResponse_major_tag 1
+#define PB_System_ProtobufVersionResponse_minor_tag 2
 #define PB_System_RebootRequest_mode_tag         1
 #define PB_System_GetDateTimeResponse_datetime_tag 1
 #define PB_System_SetDateTimeRequest_datetime_tag 1
@@ -187,6 +202,17 @@ X(a, STATIC,   SINGULAR, UINT32,   weekday,           7)
 #define PB_System_PlayAudiovisualAlertRequest_CALLBACK NULL
 #define PB_System_PlayAudiovisualAlertRequest_DEFAULT NULL
 
+#define PB_System_ProtobufVersionRequest_FIELDLIST(X, a) \
+
+#define PB_System_ProtobufVersionRequest_CALLBACK NULL
+#define PB_System_ProtobufVersionRequest_DEFAULT NULL
+
+#define PB_System_ProtobufVersionResponse_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, UINT32,   major,             1) \
+X(a, STATIC,   SINGULAR, UINT32,   minor,             2)
+#define PB_System_ProtobufVersionResponse_CALLBACK NULL
+#define PB_System_ProtobufVersionResponse_DEFAULT NULL
+
 extern const pb_msgdesc_t PB_System_PingRequest_msg;
 extern const pb_msgdesc_t PB_System_PingResponse_msg;
 extern const pb_msgdesc_t PB_System_RebootRequest_msg;
@@ -198,6 +224,8 @@ extern const pb_msgdesc_t PB_System_GetDateTimeResponse_msg;
 extern const pb_msgdesc_t PB_System_SetDateTimeRequest_msg;
 extern const pb_msgdesc_t PB_System_DateTime_msg;
 extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg;
+extern const pb_msgdesc_t PB_System_ProtobufVersionRequest_msg;
+extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg;
 
 /* Defines for backwards compatibility with code written before nanopb-0.4.0 */
 #define PB_System_PingRequest_fields &PB_System_PingRequest_msg
@@ -211,6 +239,8 @@ extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg;
 #define PB_System_SetDateTimeRequest_fields &PB_System_SetDateTimeRequest_msg
 #define PB_System_DateTime_fields &PB_System_DateTime_msg
 #define PB_System_PlayAudiovisualAlertRequest_fields &PB_System_PlayAudiovisualAlertRequest_msg
+#define PB_System_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_msg
+#define PB_System_ProtobufVersionResponse_fields &PB_System_ProtobufVersionResponse_msg
 
 /* Maximum encoded size of messages (where known) */
 /* PB_System_PingRequest_size depends on runtime parameters */
@@ -222,6 +252,8 @@ extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg;
 #define PB_System_GetDateTimeRequest_size        0
 #define PB_System_GetDateTimeResponse_size       24
 #define PB_System_PlayAudiovisualAlertRequest_size 0
+#define PB_System_ProtobufVersionRequest_size    0
+#define PB_System_ProtobufVersionResponse_size   12
 #define PB_System_RebootRequest_size             2
 #define PB_System_SetDateTimeRequest_size        24
 

+ 1 - 1
assets/protobuf

@@ -1 +1 @@
-Subproject commit 5409d34a29073f5b51acad1cb5c24663f4e625e2
+Subproject commit 93b9cf3af76664a27646494341a63281a9022740

+ 9 - 3
firmware/targets/f6/furi_hal/furi_hal_info.c

@@ -1,6 +1,7 @@
 #include <furi_hal_info.h>
 #include <furi_hal.h>
 #include <shci.h>
+#include <protobuf_version.h>
 
 void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) {
     string_t value;
@@ -127,10 +128,15 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) {
         bool enclave_valid = furi_hal_crypto_verify_enclave(&enclave_keys, &enclave_valid_keys);
         string_printf(value, "%d", enclave_valid_keys);
         out("enclave_valid_keys", string_get_cstr(value), false, context);
-        out("enclave_valid", enclave_valid ? "true" : "false", true, context);
+        out("enclave_valid", enclave_valid ? "true" : "false", false, context);
     } else {
-        out("radio_alive", "false", true, context);
+        out("radio_alive", "false", false, context);
     }
 
+    string_printf(value, "%u", PROTOBUF_MAJOR_VERSION);
+    out("protobuf_version_major", string_get_cstr(value), false, context);
+    string_printf(value, "%u", PROTOBUF_MINOR_VERSION);
+    out("protobuf_version_minor", string_get_cstr(value), true, context);
+
     string_clear(value);
-}
+}

+ 9 - 3
firmware/targets/f7/furi_hal/furi_hal_info.c

@@ -1,6 +1,7 @@
 #include <furi_hal_info.h>
 #include <furi_hal.h>
 #include <shci.h>
+#include <protobuf_version.h>
 
 void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) {
     string_t value;
@@ -127,10 +128,15 @@ void furi_hal_info_get(FuriHalInfoValueCallback out, void* context) {
         bool enclave_valid = furi_hal_crypto_verify_enclave(&enclave_keys, &enclave_valid_keys);
         string_printf(value, "%d", enclave_valid_keys);
         out("enclave_valid_keys", string_get_cstr(value), false, context);
-        out("enclave_valid", enclave_valid ? "true" : "false", true, context);
+        out("enclave_valid", enclave_valid ? "true" : "false", false, context);
     } else {
-        out("radio_alive", "false", true, context);
+        out("radio_alive", "false", false, context);
     }
 
+    string_printf(value, "%u", PROTOBUF_MAJOR_VERSION);
+    out("protobuf_version_major", string_get_cstr(value), false, context);
+    string_printf(value, "%u", PROTOBUF_MINOR_VERSION);
+    out("protobuf_version_minor", string_get_cstr(value), true, context);
+
     string_clear(value);
-}
+}