Skip to content

kgui: KodeOS does not build with CONFIG_KODEOS_RADIO=n (radio and network calls outside their guards) #67

Open

Description

@mquerostudio

@jbenedictocenteno, for you to look at and decide; nothing is in a branch.

What failed

KodeOS does not build with CONFIG_KODEOS_RADIO=n, which is how kode-sim (the Kode Dot simulator on Espressif's esp-emu) builds it: there is no C5 in the emulator, so it leaves the radio out. On the board nothing changes, as the radio is always on there.

  • Host: macOS 26 (Apple silicon). ESP-IDF: v6.1.
  • Revisions: KodeOS develop db93026, its sdk/ at 21029b6.
  • Build: KodeOS's own sdkconfig.defaults plus CONFIG_KODEOS_RADIO=n (and CONFIG_KODE_TEST_DOT=n, whose #error says it needs the radio).

Output

Compiling components/kgui/kgui_ao.c:

kgui_ao.c:24726:36: error: implicit declaration of function 'gui_radio_words'
kgui_ao.c:24738:40: error: format '%s' expects argument of type 'char *', but argument 4 has type 'int'
kgui_ao.c:3245:13: error: 'gui_ble_name_send' used but never defined [-Werror]

With those two fixed, the link:

undefined reference to `radio_boot_hold'        (Gui_initial)
undefined reference to `radio_boot_release'     (gui_keep_gate)
undefined reference to `net_http_ask'           (gui_os_ask)
undefined reference to `net_stream_open_request', `net_stream_read_request',
  `net_stream_return', `net_stream_close_request', `net_stream_buf'   (kgui_assets.c, gather*)

Why

kgui calls the radio's and AO_Net's API outside the guards their own sources are built under. kaos/CMakeLists.txt builds radio_ao.c only with CONFIG_KODEOS_RADIO, and net_ao.c only with RADIO, WIFI and NET. kaos.h says so next to the radio calls ("Compiled under CONFIG_KODEOS_RADIO; guard the call the same way"). In kgui:

  • gui_radio_words() is defined under CONFIG_KODEOS_WIFI, but gui_more_value() uses it for the Wi-Fi and Bluetooth rows of "More" with no guard.
  • gui_ble_name_send() is defined under CONFIG_KODEOS_BLE; its prototype and its call in Gui_running (the ble_name_owed send) are not guarded.
  • radio_boot_hold() and radio_boot_release() are called with no guard.
  • gui_os_ask() calls net_http_ask(), and kgui_assets.c's gatherer calls net_stream_*(), with no guard.

How it can be solved

Guard each call as its definition is guarded, with an answer for a build without it:

  • More's Wi-Fi and Bluetooth rows: "Off" without KODEOS_WIFI or KODEOS_BLE.
  • The BLE name: prototypes and the send under KODEOS_BLE.
  • The boot hold and release: under KODEOS_RADIO.
  • The update check: without KODEOS_NET, gui_os_failed(me, "built without the network").
  • The gatherer: without KODEOS_NET, a URL fails at once (gather_fail(KODE_DENIED)); the close, read, buffer and return branches for a stream are under KODEOS_NET.

The words "Off" and "built without the network" are a suggestion. 35 lines in two files; the diff below is what I tried.

Tested

With this diff and the display fix in kodediy/kode-sdk#122 (kdrv's drain after a panel read, which otherwise hangs the display task with no DSI host), KodeOS builds without the radio. kode-sim's emulator suite then passes 25 of 25 on it:

  • it boots to its UI;
  • installs an app over the console (install src="terminal") and goes home by the held button and by reset, with the glass kept lit;
  • mounts the card;
  • the battery and ship mode;
  • the clock with no network;
  • review.

Not run: tools/ checks of KodeOS (size, layers, MISRA), and anything on a board, where this changes nothing.

The diff (against develop db93026)
diff --git a/components/kgui/kgui_ao.c b/components/kgui/kgui_ao.c
index c093ac5..d9b2656 100644
--- a/components/kgui/kgui_ao.c
+++ b/components/kgui/kgui_ao.c
@@ -3241,9 +3241,11 @@ static void gui_more_fill(Gui * const me);
 static void gui_time_fill(Gui * const me);
 static void gui_time_follow(Gui * const me);
 static uint32_t gui_time_minute(Gui const * const me, struct tm *out);
+#if CONFIG_KODEOS_BLE
 static const char *gui_ble_name_shown(Gui const * const me);
 static void gui_ble_name_send(Gui const * const me);
 static void gui_ble_name_config(Gui * const me, KodeConfigReqEvt const * const r);
+#endif
 static bool gui_row_cut(Gui const * const me, int32_t cy, kgui_rail_t const *edge);
 static void gui_vol_motor(Gui const * const me);
 static void gui_first_hold_tick(Gui * const me);
@@ -12065,7 +12067,9 @@ static void gui_keep_gate(Gui * const me)
         && ((uint8_t)GUI_KEEP_READ_NONE == me->keep_read) )
     {
         me->keep_gate_open = true;
+#if CONFIG_KODEOS_RADIO
         radio_boot_release();
+#endif
     }
 }
 
@@ -24595,6 +24599,7 @@ static void gui_os_ask(Gui * const me, const char *why)
         gui_os_failed(me, "no memory for the answer");
         return;
     }
+#if CONFIG_KODEOS_NET
     if ( net_http_ask(&me->super, false, GUI_OS_SERVICE, NULL, 0U, NULL,
                       me->os->answer, KGUI_OSREL_ANSWER_MAX) == KODE_OK )
     {
@@ -24605,6 +24610,10 @@ static void gui_os_ask(Gui * const me, const char *why)
     {
         gui_os_failed(me, "AO_Net did not take the question");
     }
+#else
+    (void)why;
+    gui_os_failed(me, "built without the network");
+#endif
 }
 
 /**
@@ -24723,6 +24732,7 @@ static void gui_more_value(Gui const * const me, uint8_t which, char *out,
             break;
         }
         case GUI_MORE_WIFI: {
+#if CONFIG_KODEOS_WIFI
             const char * const w = gui_radio_words(me, me->wifi_on, me->wifi_linked,
                                                    me->wifi_reconnecting);
             const char *say = me->wifi_ssid;
@@ -24732,10 +24742,17 @@ static void gui_more_value(Gui const * const me, uint8_t which, char *out,
                 say = w;
             }
             (void)snprintf(out, cap, "%s", say);
+#else
+            (void)snprintf(out, cap, "%s", "Off");   /* built without Wi-Fi */
+#endif
             break;
         }
         case GUI_MORE_BLE: {
+#if CONFIG_KODEOS_BLE
             (void)snprintf(out, cap, "%s", gui_radio_words(me, me->ble_on, false, false));
+#else
+            (void)snprintf(out, cap, "%s", "Off");   /* built without Bluetooth */
+#endif
             break;
         }
         case GUI_MORE_TIME: {
@@ -33389,7 +33406,9 @@ static QState Gui_initial(Gui * const me, void const * const par)
     {
         kgui_assets_start();
     }
+#if CONFIG_KODEOS_RADIO
     radio_boot_hold();
+#endif
     /* The name chosen for Bluetooth: the radio keeps it for its adverts. It
      * is sent once every owner has its queue (GUI_TICK_SIG): this AO starts
      * in kode_init()'s early row, before AO_Radio, and a post to an AO with
@@ -33670,11 +33689,13 @@ static QState Gui_running(Gui * const me, QEvt const * const e)
                 me->settings_owed = false;
                 gui_settings_ask();
             }
+#if CONFIG_KODEOS_BLE
             if ( me->ble_name_owed && kode_up() )
             {
                 me->ble_name_owed = false;
                 gui_ble_name_send(me);
             }
+#endif
             /* The long step of the whole system, which is why AO_Gui sits
              * near the bottom of the priority list, with only AO_Net below
              * it: a repaint spends most of its time blocked inside LVGL
diff --git a/components/kgui/kgui_assets.c b/components/kgui/kgui_assets.c
index b58415e..0dde167 100644
--- a/components/kgui/kgui_assets.c
+++ b/components/kgui/kgui_assets.c
@@ -471,6 +471,8 @@ static void say_source(bool state)
 
 /* ---- The gatherer: one file, read whole, into one PSRAM block --------------- */
 
+static void gather_fail(kode_status_t rc);
+
 /**
  * @brief Start reading a whole file from a path or a URL.
  * @param net   true for a URL (AO_Net's stream), false for a path.
@@ -492,7 +494,11 @@ static void gather(bool net, const char *where, uint32_t limit)
     s_a.g_probing = false;
     if ( net )
     {
+#if CONFIG_KODEOS_NET
         net_stream_open_request(s_a.g_where, s_a.ao);
+#else
+        gather_fail(KODE_DENIED);          /* built without the network: no URL opens */
+#endif
     }
     else
     {
@@ -503,11 +509,13 @@ static void gather(bool net, const char *where, uint32_t limit)
 /** @brief Close the gather's file or stream; buffers on loan go back with it. */
 static void gather_close(void)
 {
+#if CONFIG_KODEOS_NET
     if ( s_a.g_net )
     {
         net_stream_close_request();
     }
     else
+#endif
     {
         storage_close_request();
     }
@@ -569,11 +577,13 @@ static void gather_opened(StorageOpenRspEvt const * const r)
         gather_fail(KODE_NO_RESOURCES);
         return;
     }
+#if CONFIG_KODEOS_NET
     if ( s_a.g_net )
     {
         net_stream_read_request();
     }
     else
+#endif
     {
         storage_read_request();
     }
@@ -624,11 +634,13 @@ static void gather_data(StorageDataEvt const * const d)
 {
     const uint8_t *src = NULL;
 
+#if CONFIG_KODEOS_NET
     if ( s_a.g_net )
     {
         src = net_stream_buf(d->idx);
     }
     else
+#endif
     {
         src = storage_buf(d->idx);
     }
@@ -655,10 +667,12 @@ static void gather_data(StorageDataEvt const * const d)
         s_a.op = OP_NONE;
         post_result(KODE_OK, true);
     }
+#if CONFIG_KODEOS_NET
     else if ( s_a.g_net )
     {
         net_stream_return(d->idx);         /* a return IS the next read */
     }
+#endif
     else
     {
         storage_next_request(d->idx);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions