Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/lvgldemo/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ config EXAMPLES_LVGLDEMO_STACKSIZE
int "lvgldemo stack size"
default 16384

config EXAMPLES_LVGLDEMO_UTOUCH_DEVPATH
string "Second pointer device path"
depends on INPUT_TOUCHSCREEN
---help---
Optional second pointer device, opened alongside the primary
touchscreen: both drive the same UI. A VNC server's remote
pointer device is the usual tenant. Leave empty for none.

config EXAMPLES_LVGLDEMO_INPUT_DEVPATH
string "Touchscreen device path"
default "/dev/input0"
Expand Down
12 changes: 12 additions & 0 deletions examples/lvgldemo/lvgldemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ int main(int argc, FAR char *argv[])

#ifdef CONFIG_INPUT_TOUCHSCREEN
info.input_path = CONFIG_EXAMPLES_LVGLDEMO_INPUT_DEVPATH;
#ifdef CONFIG_EXAMPLES_LVGLDEMO_UTOUCH_DEVPATH
/* A second pointer device, a VNC server's remote pointer, say,
* alongside the physical touchscreen rather than instead of it. An
* empty string means none: a string option always exists, only its
* content says whether it was configured.
*/

if (CONFIG_EXAMPLES_LVGLDEMO_UTOUCH_DEVPATH[0] != '\0')
{
info.utouch_path = CONFIG_EXAMPLES_LVGLDEMO_UTOUCH_DEVPATH;
}
#endif
#endif

lv_nuttx_init(&info, &result);
Expand Down
178 changes: 178 additions & 0 deletions include/netutils/fbvnc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/****************************************************************************
* apps/include/netutils/fbvnc.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

#ifndef __APPS_INCLUDE_NETUTILS_FBVNC_H
#define __APPS_INCLUDE_NETUTILS_FBVNC_H

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <stdbool.h>
#include <stdint.h>

/****************************************************************************
* Public Types
****************************************************************************/

/* Dirty rectangle descriptor */

struct fbvnc_rect_s
{
uint16_t x;
uint16_t y;
uint16_t w;
uint16_t h;
};

/* Snapshot callback.
*
* Called by the server whenever a client asks for a framebuffer update.
* The caller owns the pixel data: this is what keeps the server free of
* a framebuffer of its own, so that it can stream the display's own
* memory without a copy.
*
* The callback fills in the rectangles that changed since the last call
* and returns the base of the framebuffer, or NULL if no snapshot could
* be taken. Returning zero rectangles is not an error; it means
* nothing changed.
*
* Note that this runs on the server thread. Do not block on a lock that
* the render thread may already hold.
*/

typedef CODE FAR const uint8_t *
(*fbvnc_snapshot_t)(FAR struct fbvnc_rect_s *rects,
uint32_t maxrects, FAR uint32_t *nrects);

/* Connection notification callback */

typedef CODE void (*fbvnc_event_t)(void);

/* Remote input callbacks. Both run on the server thread: hand the event
* to the UI thread, do not call into the UI from here.
*
* Pointer: position in framebuffer coordinates plus the RFB button mask
* (bit 0 = left, 1 = middle, 2 = right, bits 3-6 = scroll wheel notches
* encoded as press+release pairs).
*
* Key: the X11 keysym as the client sent it. Printable characters
* arrive already shifted, Shift+a comes in as 'A', so only special
* keys (arrows, enter, backspace...) need translating.
*/

typedef CODE void (*fbvnc_pointer_t)(uint16_t x, uint16_t y,
uint8_t buttons);
typedef CODE void (*fbvnc_key_t)(uint32_t keysym, bool pressed);

/* Server configuration. Must remain valid for the lifetime of the
* server: the start function stores the pointer's contents, not a copy
* of the callbacks' arguments.
*/

struct fbvnc_cfg_s
{
fbvnc_snapshot_t snapshot; /* Mandatory */
fbvnc_event_t on_connect; /* Optional, may be NULL */
fbvnc_event_t on_disconnect; /* Optional, may be NULL */

/* Optional. Invoked when the client asks for a non-incremental
* update, i.e. it wants the whole screen again. Use it to force the
* next snapshot to report the full canvas as dirty.
*/

fbvnc_event_t on_invalidate;

/* Optional. Remote input; NULL means the events are discarded. */

fbvnc_pointer_t on_pointer;
fbvnc_key_t on_key;

/* Geometry of the served framebuffer. Zero means the compile-time
* defaults; a daemon serving an arbitrary framebuffer fills these in
* from what the device reports. Only 16-bit RGB565 is served either
* way.
*/

uint16_t width;
uint16_t height;
uint16_t stride; /* Bytes per row */
};

/****************************************************************************
* Public Function Prototypes
****************************************************************************/

#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif

/****************************************************************************
* Name: fbvnc_start
*
* Description:
* Start the VNC server thread. The server listens on
* CONFIG_NETUTILS_FBVNC_PORT and accepts one client at a time.
*
* Input Parameters:
* cfg - Server configuration. The snapshot callback is mandatory.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/

int fbvnc_start(FAR const struct fbvnc_cfg_s *cfg);

/****************************************************************************
* Name: fbvnc_stop
*
* Description:
* Stop the VNC server. Closes the client connection if there is one
* and terminates the server thread.
*
****************************************************************************/

void fbvnc_stop(void);

/****************************************************************************
* Name: fbvnc_is_connected
*
* Description:
* Return true if a VNC client is currently connected.
*
****************************************************************************/

bool fbvnc_is_connected(void);

#undef EXTERN
#ifdef __cplusplus
}
#endif

#endif /* __APPS_INCLUDE_NETUTILS_FBVNC_H */
25 changes: 25 additions & 0 deletions netutils/fbvnc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ##############################################################################
# apps/netutils/fbvnc/CMakeLists.txt
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
# license agreements. See the NOTICE file distributed with this work for
# additional information regarding copyright ownership. The ASF licenses this
# file to you under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
#
# ##############################################################################

if(CONFIG_NETUTILS_FBVNC)
target_sources(apps PRIVATE fbvnc.c)
endif()
157 changes: 157 additions & 0 deletions netutils/fbvnc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#

menuconfig NETUTILS_FBVNC
bool "VNC server (RFB 3.7) streaming a caller-owned framebuffer"
default n
depends on NET_TCP
---help---
A VNC Remote Frame Buffer server that streams a framebuffer the
application owns, supplied through a snapshot callback.

This is deliberately not the same thing as the VNC server in
drivers/video/vnc: that one allocates a framebuffer of its own
and registers it as another /dev/fbN, so it is a second, virtual
display. This one has no framebuffer at all and streams whatever
the caller points it at, which is what lets it mirror the display
the LCD is already showing without a duplicate copy.

if NETUTILS_FBVNC

config NETUTILS_FBVNC_PORT
int "TCP port"
default 5900
---help---
The port clients connect to. Display N in a VNC client's
address is port 5900 + N.

config NETUTILS_FBVNC_STACKSIZE
int "Server thread stack size"
default 8192

config NETUTILS_FBVNC_PRIORITY
int "Server thread priority"
default 100
---help---
Keep this below the priority of the thread that renders the UI.
The remote display is worth less than the local one: if the two
compete, the local display should win.

Note the inverted convention if you are porting a configuration
from Zephyr, where a smaller number means a higher priority.

config NETUTILS_FBVNC_NAME
string "Desktop name advertised to clients"
default "NuttX"

config NETUTILS_FBVNC_FB_WIDTH
int "Framebuffer width (pixels)"
default 1024

config NETUTILS_FBVNC_FB_HEIGHT
int "Framebuffer height (rows)"
default 600

config NETUTILS_FBVNC_FB_BYTESPP
int "Framebuffer bytes per pixel"
default 2
range 2 2
---help---
Only 2 (RGB565) is implemented so far.

The wire format deliberately matches the framebuffer rather than
being promoted to 32bpp RGBA. Promoting doubles the bytes per
frame, and at this resolution that is the difference between
1.2 MiB and 2.4 MiB per full redraw -- enough to exhaust the
Ethernet driver's buffer pool during sustained navigation.

config NETUTILS_FBVNC_MAX_DIRTY
int "Maximum dirty rectangles per update"
default 32
---help---
How many rectangles the snapshot callback may report. When the
application has more changed regions than this it should collapse
them into one full-screen rectangle rather than dropping any.

config NETUTILS_FBVNC_SEND_CHUNK
int "Maximum bytes per send() call"
default 8192

config NETUTILS_FBVNC_ENCODING_HEXTILE
bool "Hextile encoding (RFB 7.7.4)"
default y
---help---
Tile-based encoding, 16x16 tiles, each described as a fill, as
runs of a foreground colour over a background, or as raw pixels.

On a user interface most tiles are a single colour, and a solid
tile costs three bytes against 512 raw. That is the difference
between a first frame that arrives and one that does not: a
1024x600 screen is 1.2 MiB raw, and this link cannot carry that
while the display is being redrawn.

All of the codec is here -- no zlib, no jpeg. ZRLE and Tight
compress better but need both, and a per-session deflate
context besides.

Falls back to Raw when the client does not ask for Hextile, or
when it has negotiated a pixel format other than the
framebuffer's own.

config NETUTILS_FBVNC_MIN_UPDATE_MS
int "Minimum time between framebuffer updates (ms)"
default 100
---help---
A floor on the time between two consecutive answers to a client
asking for a framebuffer update, no matter how fast it asks.
100 ms is a ceiling of 10 updates per second.

Clients ask again the instant they have finished parsing the
last answer, which while a list is being dragged means a full
screen is in flight permanently and the display never catches
up. Delaying the answer is not a protocol violation; the
client is already waiting for one.

Set to 0 to answer as fast as the client asks.

config NETUTILS_FBVNC_SEND_TIMEOUT
int "Send timeout (seconds)"
default 30
---help---
Disconnect the client if a send blocks for longer than this. On
a wedged connection this is what gets the server back to
accepting new clients.

endif # NETUTILS_FBVNC

config NETUTILS_FBVNC_TRACE
bool "Log what every update cost"
default n
---help---
Report, for each update sent, how many rectangles it carried,
how many bytes they cover, and how long the snapshot and the
sending each took.

This is how one tells a slow link from a slow application: a
large send time is the network, a large snapshot time is
whatever produced the pixels. It is a line of output per
update, which is far too much to leave on, so it is asked for
rather than assumed.

config NETUTILS_FBVNC_ENCODING_TRLE
bool "TRLE encoding (RFB 7.7.5)"
default y
---help---
Send a tile of few colours as a palette and an index per pixel
rather than as a list of sub-rectangles.

A widget toolkit draws flat panels and text, so most tiles have
one or two colours; two colours cost one bit per pixel here,
against a sub-rectangle each in Hextile. Offered to clients
that ask for it, and preferred over Hextile when both are
offered.

Only the native pixel format is served this way. A client that
negotiates another gets Raw, converted.
Loading
Loading