Skip to content

Commit ce6c2e5

Browse files
committed
system/nxstore: add LVGL app-store UI
Add nxstore, an LVGL-based frontend for nxpkg (system/nxpkg): lists packages from the local index, installs/launches the selected one, and supervises whatever it hands the screen to. Card-based app list (populate_app_list()): each row shows name, version, and description/status, install/launch state reflected via icon glyph and color (LV_SYMBOL_DOWNLOAD/PLAY, accent/success color), and a sliding-segment progress bar during install (no real byte-level progress is available from pkg_install(), so this reads as 'actively working' without fabricating a percentage). Explicit LV_STATE_PRESSED styling on every tappable row/button, since no LVGL theme is loaded and a tap would otherwise give no visual feedback at all. Supervisor screen (build_run_screen()/nxstore_enter_running_screen()): a launched app (e.g. a game that owns /dev/fb0 directly, not just another LVGL client) gets a dedicated screen with a name label and a Close button, confined to the border region the launched app's own scaled/centered framebuffer output never draws into, so switching back to it doesn't fight over pixels with whatever the app already put in the framebuffer. Close/reap handling (close_running_app_event_cb()/ nxstore_poll_running_app()): sends SIGTERM and polls waitpid(WNOHANG) for the launched pid, but explicitly also treats waitpid() returning ECHILD as 'already gone' rather than 'still running' - both the close-button handler and the passive per-loop poll independently race to reap the same child, so whichever one loses that race must not spin forever waiting for a wait() that can now never succeed. Requires the target app to install its own SIGTERM handler to exit cleanly (this is why there is no generic force-kill fallback here: an earlier version of this code called task_delete() when SIGTERM wasn't reaped quickly enough, which was found on real hardware to hang the entire board - not just the one task - when it landed mid framebuffer/heap access on this flat-memory build). Toast notifications (nxstore_toast()) provide a transient, unmissable confirmation for install/uninstall/launch outcomes and app-closed events, additive to the durable per-row subtitle text rather than a replacement for it. nxstore's own boot-time catalog sync waits (bounded, 15s) on g_wifi_dhcp_ret before attempting a network fetch, since Wi-Fi association completing doesn't imply DHCP has - an HTTP fetch attempted in that window fails with -ENETUNREACH even though the link itself is already up, indistinguishable from being genuinely offline without this wait. Signed-off-by: aviralgarg05 <gargaviral99@gmail.com>
1 parent d33ae3b commit ce6c2e5

6 files changed

Lines changed: 1905 additions & 0 deletions

File tree

system/nxstore/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# ##############################################################################
2+
# apps/system/nxstore/CMakeLists.txt
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
7+
# license agreements. See the NOTICE file distributed with this work for
8+
# additional information regarding copyright ownership. The ASF licenses this
9+
# file to you under the Apache License, Version 2.0 (the "License"); you may not
10+
# use this file except in compliance with the License. You may obtain a copy of
11+
# the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations under
19+
# the License.
20+
#
21+
# ##############################################################################
22+
23+
if(CONFIG_SYSTEM_NXSTORE)
24+
nuttx_add_application(
25+
NAME
26+
${CONFIG_SYSTEM_NXSTORE_PROGNAME}
27+
PRIORITY
28+
${CONFIG_SYSTEM_NXSTORE_PRIORITY}
29+
STACKSIZE
30+
${CONFIG_SYSTEM_NXSTORE_STACKSIZE}
31+
MODULE
32+
${CONFIG_SYSTEM_NXSTORE}
33+
SRCS
34+
nxstore_main.c)
35+
endif()

system/nxstore/Kconfig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# For a description of the syntax of this configuration file,
3+
# see the file kconfig-language.txt in the NuttX tools repository.
4+
#
5+
6+
config SYSTEM_NXSTORE
7+
tristate "Nxstore LVGL App Store"
8+
default n
9+
depends on GRAPHICS_LVGL && SYSTEM_NXPKG
10+
select NETUTILS_CJSON
11+
---help---
12+
Enable the Nxstore LVGL graphical application store frontend.
13+
Lists packages from the local nxpkg repository, installs the
14+
selected one via nxpkg, and launches it.
15+
16+
if SYSTEM_NXSTORE
17+
18+
config SYSTEM_NXSTORE_PROGNAME
19+
string "Program name"
20+
default "nxstore"
21+
22+
config SYSTEM_NXSTORE_PRIORITY
23+
int "nxstore task priority"
24+
default 100
25+
26+
config SYSTEM_NXSTORE_STACKSIZE
27+
int "nxstore stack size"
28+
default 8192
29+
30+
endif

system/nxstore/Make.defs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
############################################################################
2+
# apps/system/nxstore/Make.defs
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more
7+
# contributor license agreements. See the NOTICE file distributed with
8+
# this work for additional information regarding copyright ownership. The
9+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
# "License"); you may not use this file except in compliance with the
11+
# License. You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
############################################################################
22+
23+
ifneq ($(CONFIG_SYSTEM_NXSTORE),)
24+
CONFIGURED_APPS += $(APPDIR)/system/nxstore
25+
endif

system/nxstore/Makefile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
############################################################################
2+
# apps/system/nxstore/Makefile
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more
7+
# contributor license agreements. See the NOTICE file distributed with
8+
# this work for additional information regarding copyright ownership. The
9+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
# "License"); you may not use this file except in compliance with the
11+
# License. You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
############################################################################
22+
23+
include $(APPDIR)/Make.defs
24+
25+
PROGNAME = $(CONFIG_SYSTEM_NXSTORE_PROGNAME)
26+
PRIORITY = $(CONFIG_SYSTEM_NXSTORE_PRIORITY)
27+
STACKSIZE = $(CONFIG_SYSTEM_NXSTORE_STACKSIZE)
28+
MODULE = $(CONFIG_SYSTEM_NXSTORE)
29+
30+
MAINSRC = nxstore_main.c
31+
32+
include $(APPDIR)/Application.mk

system/nxstore/README.txt

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
nxstore - an LVGL touchscreen app store for NuttX
2+
=================================================
3+
4+
nxstore is a graphical front-end for system/nxpkg. It lists the
5+
packages available in a nxpkg repository, installs the one you tap via
6+
nxpkg, launches it, and supervises it with an on-screen "Close"
7+
control. It is the touchscreen equivalent of driving the nxpkg CLI by
8+
hand; both consume the same repository, so the repository/server setup
9+
(layout, how to serve it, populating it with tools/export_pkg_repo.py,
10+
pointing the board at it) is documented once, in system/nxpkg's
11+
README.txt, and is not repeated here.
12+
13+
14+
Dependencies
15+
============
16+
17+
Kconfig: SYSTEM_NXSTORE depends on GRAPHICS_LVGL and SYSTEM_NXPKG and
18+
selects NETUTILS_CJSON. It needs a working framebuffer (/dev/fb0) and
19+
a touch input device (/dev/input0) - the same graphics/input stack
20+
examples/lvgldemo uses. NETUTILS_CJSON is used to parse the
21+
repository index and package manifests.
22+
23+
24+
On-device lifecycle
25+
===================
26+
27+
1. Browse - the app list is built from the repository index nxpkg
28+
fetched. Installed packages show a launch action;
29+
not-yet-installed ones show an install action.
30+
2. Install - tapping an uninstalled package runs the nxpkg install
31+
flow (download -> sha256 verify -> transactional
32+
install) on a background worker thread, with progress
33+
shown as a toast.
34+
3. Launch - tapping an installed package spawns its payload
35+
(posix_spawn) and switches to the "running" screen: a
36+
thin bar across the top NXSTORE_BAR_HEIGHT pixels (see
37+
include/system/nxstore_chrome.h) carrying the app name
38+
and a Close button, with the rest of the framebuffer
39+
left to the running app.
40+
4. Close - see "Closing a running app" below.
41+
42+
Launched apps are given NXSTORE_LAUNCH_STACKSIZE (32 KiB) of stack -
43+
posix_spawn's default (CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE, 2 KiB) is
44+
far too small for a real LVGL/framebuffer app, and overflowing it does
45+
not fail loudly (it corrupts adjacent heap, surfacing later as a crash
46+
nowhere near the real cause).
47+
48+
49+
Closing a running app: the cooperative-SIGTERM contract
50+
=======================================================
51+
52+
This is the one thing an app author MUST get right to be launchable
53+
from nxstore.
54+
55+
The Close button sends the running app SIGTERM and waits for it to
56+
reap itself. It does NOT (and cannot safely) force-kill the task:
57+
58+
- On a build with CONFIG_SIG_DEFAULT disabled (the default), NuttX
59+
has no default action for SIGTERM at all. Delivery does nothing
60+
unless the app installs its own handler with sigaction().
61+
- An earlier nxstore fell back to task_delete() when SIGTERM went
62+
unreaped. On real hardware that force-kill landed while the app
63+
was mid framebuffer/heap access and hung the *entire board* (not
64+
just the task), requiring a physical power cycle. That fallback
65+
was removed: there is no safe way to force-terminate an arbitrary
66+
task from the outside here.
67+
68+
So an nxstore-launchable app must cooperate:
69+
70+
- Install an async-signal-safe SIGTERM handler that only sets a
71+
volatile sig_atomic_t flag.
72+
- Poll that flag from its own main loop and exit cleanly (freeing
73+
the framebuffer, restoring input state, etc.) when it is set.
74+
75+
Apps whose main loop can never block indefinitely (they run to
76+
completion on their own, or fail fast at startup) do not strictly need
77+
a handler, but any app that renders in a long-lived loop does. See
78+
these in-tree examples for the exact pattern:
79+
80+
- games/NXDoom (i_install_quit_signal / i_poll_quit_signal)
81+
- examples/calculator
82+
- games/cgol, games/brickmatch
83+
84+
If SIGTERM is not reaped within the timeout, nxstore keeps the running
85+
screen up rather than returning to the app list - switching back while
86+
the app might still be alive and drawing into the framebuffer would
87+
just reproduce the original hang, hidden.
88+
89+
90+
Configuration
91+
=============
92+
93+
SYSTEM_NXSTORE_PROGNAME program/registration name (default nxstore)
94+
SYSTEM_NXSTORE_PRIORITY task priority (default 100)
95+
SYSTEM_NXSTORE_STACKSIZE nxstore's own stack (default 8192)
96+
97+
NXSTORE_LAUNCH_STACKSIZE (the stack given to launched apps) and
98+
NXSTORE_BAR_HEIGHT (the reserved top bar) are compile-time constants in
99+
the source / include/system/nxstore_chrome.h rather than Kconfig
100+
options.

0 commit comments

Comments
 (0)