examples/vncviewer: add VNC viewer for LCD display

Add a minimal VNC viewer application that connects to a VNC server
and renders the remote desktop on a local LCD.

Features:
- RFB 3.8 protocol with VNC Authentication (DES, pure software)
- Raw encoding with pixel format auto-detected from LCD driver
- Row-by-row rendering via LCDDEVIO_PUTAREA (minimal RAM usage)
- LCD resolution and format queried at runtime via LCDDEVIO_GETVIDEOINFO
- Auto-reconnect on connection loss with 2-second retry

Usage:
  vncviewer <host> [port]
  vncviewer -p <password> <host> [port]
  vncviewer -p <password> -d <lcd_devno> <host> [port]

Assisted-by: GitHubCopilot:claude-4.6-opus
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
wangjianyu3 2026-04-23 23:16:47 +08:00 committed by CeDeROM
parent 6379e531de
commit 62f3d37041
9 changed files with 1989 additions and 0 deletions

View file

@ -0,0 +1,35 @@
# ##############################################################################
# apps/system/vncviewer/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_SYSTEM_VNCVIEWER)
nuttx_add_application(
NAME
${CONFIG_SYSTEM_VNCVIEWER_PROGNAME}
SRCS
vncviewer_main.c
rfb_protocol.c
lcd_render.c
STACKSIZE
${CONFIG_SYSTEM_VNCVIEWER_STACKSIZE}
PRIORITY
${CONFIG_SYSTEM_VNCVIEWER_PRIORITY})
endif()

32
system/vncviewer/Kconfig Normal file
View file

@ -0,0 +1,32 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config SYSTEM_VNCVIEWER
tristate "VNC Viewer"
default n
depends on NET_TCP && LCD
---help---
Enable the VNC Viewer example application.
Connects to a VNC server and displays the remote
framebuffer on a local LCD.
if SYSTEM_VNCVIEWER
config SYSTEM_VNCVIEWER_PROGNAME
string "Program name"
default "vncviewer"
---help---
This is the name of the program that will be used when the
NSH ELF program is installed.
config SYSTEM_VNCVIEWER_PRIORITY
int "VNC Viewer task priority"
default 100
config SYSTEM_VNCVIEWER_STACKSIZE
int "VNC Viewer stack size"
default 4096
endif

View file

@ -0,0 +1,25 @@
############################################################################
# apps/system/vncviewer/Make.defs
#
# 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.
#
############################################################################
ifneq ($(CONFIG_SYSTEM_VNCVIEWER),)
CONFIGURED_APPS += $(APPDIR)/system/vncviewer
endif

37
system/vncviewer/Makefile Normal file
View file

@ -0,0 +1,37 @@
############################################################################
# apps/system/vncviewer/Makefile
#
# 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.
#
############################################################################
include $(APPDIR)/Make.defs
# VNC Viewer built-in application info
PROGNAME = $(CONFIG_SYSTEM_VNCVIEWER_PROGNAME)
PRIORITY = $(CONFIG_SYSTEM_VNCVIEWER_PRIORITY)
STACKSIZE = $(CONFIG_SYSTEM_VNCVIEWER_STACKSIZE)
MODULE = $(CONFIG_SYSTEM_VNCVIEWER)
# VNC Viewer sources
MAINSRC = vncviewer_main.c
CSRCS = rfb_protocol.c lcd_render.c
include $(APPDIR)/Application.mk

View file

@ -0,0 +1,177 @@
/****************************************************************************
* apps/system/vncviewer/lcd_render.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <nuttx/video/fb.h>
#include <nuttx/lcd/lcd_dev.h>
#include "lcd_render.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: lcd_init
****************************************************************************/
int lcd_init(struct lcd_ctx_s *ctx, int devno)
{
char devpath[16];
int ret;
snprintf(devpath, sizeof(devpath), "/dev/lcd%d", devno);
ctx->fd = open(devpath, O_RDWR);
if (ctx->fd < 0)
{
printf("vncviewer: failed to open %s: %d\n", devpath, errno);
return -errno;
}
/* Query LCD resolution */
struct fb_videoinfo_s vinfo;
ret = ioctl(ctx->fd, LCDDEVIO_GETVIDEOINFO,
(unsigned long)(uintptr_t)&vinfo);
if (ret < 0)
{
printf("vncviewer: GETVIDEOINFO failed: %d\n", errno);
close(ctx->fd);
ctx->fd = -1;
return -errno;
}
else
{
ctx->xres = vinfo.xres;
ctx->yres = vinfo.yres;
ctx->fmt = vinfo.fmt;
}
printf("vncviewer: LCD %s opened (%ux%u)\n",
devpath, ctx->xres, ctx->yres);
/* Set power on */
ret = ioctl(ctx->fd, LCDDEVIO_SETPOWER, 1);
if (ret < 0)
{
printf("vncviewer: WARNING: SETPOWER failed: %d\n", errno);
}
return OK;
}
/****************************************************************************
* Name: lcd_put_row
****************************************************************************/
int lcd_put_row(struct lcd_ctx_s *ctx, uint16_t x, uint16_t y,
uint16_t w, const uint16_t *pixels)
{
struct lcddev_area_s area;
int ret;
/* Clip to LCD bounds */
if (x >= ctx->xres || y >= ctx->yres)
{
return OK;
}
if (x + w > ctx->xres)
{
w = ctx->xres - x;
}
area.row_start = y;
area.row_end = y;
area.col_start = x;
area.col_end = x + w - 1;
area.data = (uint8_t *)pixels;
ret = ioctl(ctx->fd, LCDDEVIO_PUTAREA, (unsigned long)(uintptr_t)&area);
if (ret < 0)
{
return -errno;
}
return OK;
}
/****************************************************************************
* Name: lcd_fill
****************************************************************************/
int lcd_fill(struct lcd_ctx_s *ctx, uint16_t color)
{
uint16_t y;
uint16_t i;
uint16_t w = ctx->xres;
FAR uint16_t *rowbuf;
rowbuf = (FAR uint16_t *)malloc(w * sizeof(uint16_t));
if (rowbuf == NULL)
{
return -ENOMEM;
}
for (i = 0; i < w; i++)
{
rowbuf[i] = color;
}
for (y = 0; y < ctx->yres; y++)
{
lcd_put_row(ctx, 0, y, w, rowbuf);
}
free(rowbuf);
return OK;
}
/****************************************************************************
* Name: lcd_uninit
****************************************************************************/
void lcd_uninit(struct lcd_ctx_s *ctx)
{
if (ctx->fd >= 0)
{
close(ctx->fd);
ctx->fd = -1;
}
}

View file

@ -0,0 +1,106 @@
/****************************************************************************
* apps/system/vncviewer/lcd_render.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_SYSTEM_VNCVIEWER_LCD_RENDER_H
#define __APPS_SYSTEM_VNCVIEWER_LCD_RENDER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
/****************************************************************************
* Public Types
****************************************************************************/
struct lcd_ctx_s
{
int fd; /* File descriptor for /dev/lcdN */
uint16_t xres; /* LCD horizontal resolution */
uint16_t yres; /* LCD vertical resolution */
uint8_t fmt; /* Pixel format (FB_FMT_*) */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: lcd_init
*
* Description:
* Open and initialize the LCD device.
*
* Input Parameters:
* ctx - LCD context to initialize
* devno - LCD device number (0 for /dev/lcd0)
*
* Returned Value:
* OK on success, negative errno on failure.
*
****************************************************************************/
int lcd_init(struct lcd_ctx_s *ctx, int devno);
/****************************************************************************
* Name: lcd_put_row
*
* Description:
* Write a single row of pixels to the LCD.
*
* Input Parameters:
* ctx - LCD context
* x - Starting X coordinate
* y - Y coordinate (row)
* w - Width in pixels
* pixels - Pixel data matching LCD native format
*
* Returned Value:
* OK on success, negative errno on failure.
*
****************************************************************************/
int lcd_put_row(struct lcd_ctx_s *ctx, uint16_t x, uint16_t y,
uint16_t w, const uint16_t *pixels);
/****************************************************************************
* Name: lcd_fill
*
* Description:
* Fill the entire LCD with a solid color.
*
****************************************************************************/
int lcd_fill(struct lcd_ctx_s *ctx, uint16_t color);
/****************************************************************************
* Name: lcd_uninit
*
* Description:
* Close the LCD device.
*
****************************************************************************/
void lcd_uninit(struct lcd_ctx_s *ctx);
#endif /* __APPS_SYSTEM_VNCVIEWER_LCD_RENDER_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,220 @@
/****************************************************************************
* apps/system/vncviewer/rfb_protocol.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_SYSTEM_VNCVIEWER_RFB_PROTOCOL_H
#define __APPS_SYSTEM_VNCVIEWER_RFB_PROTOCOL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* RFB Protocol Version */
#define RFB_VERSION_STRING "RFB 003.008\n"
#define RFB_VERSION_LEN 12
/* Security Types */
#define RFB_SEC_INVALID 0
#define RFB_SEC_NONE 1
#define RFB_SEC_VNC_AUTH 2
/* Client-to-Server Message Types */
#define RFB_SET_PIXEL_FORMAT 0
#define RFB_SET_ENCODINGS 2
#define RFB_FB_UPDATE_REQUEST 3
#define RFB_KEY_EVENT 4
#define RFB_POINTER_EVENT 5
#define RFB_CLIENT_CUT_TEXT 6
/* Server-to-Client Message Types */
#define RFB_FB_UPDATE 0
#define RFB_SET_COLORMAP 1
#define RFB_BELL 2
#define RFB_SERVER_CUT_TEXT 3
/* Encoding Types */
#define RFB_ENCODING_RAW 0
/****************************************************************************
* Public Types
****************************************************************************/
/* Pixel format (negotiated with server based on LCD) */
struct rfb_pixel_format_s
{
uint8_t bits_per_pixel; /* 16 */
uint8_t depth; /* 16 */
uint8_t big_endian; /* 0 = little-endian */
uint8_t true_color; /* 1 */
uint16_t red_max; /* 31 (5 bits) */
uint16_t green_max; /* 63 (6 bits) */
uint16_t blue_max; /* 31 (5 bits) */
uint8_t red_shift; /* 11 */
uint8_t green_shift; /* 5 */
uint8_t blue_shift; /* 0 */
uint8_t padding[3];
};
/* Server init message (parsed) */
struct rfb_server_init_s
{
uint16_t fb_width;
uint16_t fb_height;
struct rfb_pixel_format_s pixel_format;
char name[256];
};
/* Framebuffer update rectangle header */
struct rfb_rect_hdr_s
{
uint16_t x;
uint16_t y;
uint16_t w;
uint16_t h;
int32_t encoding;
};
/* RFB connection context */
struct rfb_conn_s
{
int sockfd;
uint16_t fb_width;
uint16_t fb_height;
uint16_t view_width;
uint16_t view_height;
uint8_t bpp; /* Bytes per pixel */
char name[256];
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: rfb_connect
*
* Description:
* Establish TCP connection to VNC server.
*
* Input Parameters:
* host - Server IP address string
* port - Server port number
*
* Returned Value:
* Socket fd on success, negative errno on failure.
*
****************************************************************************/
int rfb_connect(const char *host, uint16_t port);
/****************************************************************************
* Name: rfb_handshake
*
* Description:
* Perform RFB protocol handshake: version, security, init.
*
* Input Parameters:
* conn - RFB connection context (sockfd must be set)
* password - VNC password (NULL or empty for no auth)
*
* Returned Value:
* OK on success, negative errno on failure.
*
****************************************************************************/
int rfb_handshake(struct rfb_conn_s *conn, const char *password);
/****************************************************************************
* Name: rfb_set_pixel_format
*
* Description:
* Send SetPixelFormat message based on LCD pixel format.
*
****************************************************************************/
int rfb_set_pixel_format(struct rfb_conn_s *conn, uint8_t fmt);
/****************************************************************************
* Name: rfb_set_encodings
*
* Description:
* Send SetEncodings message (Raw only).
*
****************************************************************************/
int rfb_set_encodings(struct rfb_conn_s *conn);
/****************************************************************************
* Name: rfb_request_update
*
* Description:
* Send FramebufferUpdateRequest.
*
* Input Parameters:
* conn - RFB connection
* incremental - true for incremental update
* x, y, w, h - Region to request
*
****************************************************************************/
int rfb_request_update(struct rfb_conn_s *conn, bool incremental,
uint16_t x, uint16_t y, uint16_t w, uint16_t h);
/****************************************************************************
* Name: rfb_recv_update
*
* Description:
* Receive and process one server message. For FramebufferUpdate,
* calls the provided callback for each rectangle.
*
* Input Parameters:
* conn - RFB connection
* rect_cb - Callback for each received rectangle
* arg - User argument passed to callback
*
* Returned Value:
* OK on success, negative errno on failure.
*
****************************************************************************/
typedef void (*rfb_rect_cb_t)(const struct rfb_rect_hdr_s *rect,
const uint8_t *pixels, void *arg);
int rfb_recv_update(struct rfb_conn_s *conn, rfb_rect_cb_t rect_cb,
void *arg);
#endif /* __APPS_SYSTEM_VNCVIEWER_RFB_PROTOCOL_H */

View file

@ -0,0 +1,306 @@
/****************************************************************************
* apps/system/vncviewer/vncviewer_main.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <nuttx/video/fb.h>
#include "rfb_protocol.h"
#include "lcd_render.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define VNCVIEWER_DEFAULT_PORT 5900
#define VNCVIEWER_DEFAULT_LCD 0
#define COLOR_BLACK 0x0000
/****************************************************************************
* Private Data
****************************************************************************/
static struct lcd_ctx_s g_lcd;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: rect_callback
*
* Description:
* Called for each row of pixel data received from VNC server.
* Writes directly to LCD, clipping to screen bounds.
*
****************************************************************************/
static void rect_callback(const struct rfb_rect_hdr_s *rect,
const uint8_t *pixels, void *arg)
{
/* rect->h is always 1 (row-by-row from rfb_recv_update) */
if (rect->y < g_lcd.yres && rect->x < g_lcd.xres)
{
uint16_t w = rect->w;
if (rect->x + w > g_lcd.xres)
{
w = g_lcd.xres - rect->x;
}
lcd_put_row(&g_lcd, rect->x, rect->y, w, (const uint16_t *)pixels);
}
}
/****************************************************************************
* Name: show_usage
****************************************************************************/
static void show_usage(const char *progname)
{
printf("Usage: %s [options] <host> [port]\n", progname);
printf("Options:\n");
printf(" -p <password> VNC password\n");
printf(" -d <devno> LCD device number (default: %d)\n",
VNCVIEWER_DEFAULT_LCD);
printf(" -h Show this help\n");
printf("Default port: %d\n", VNCVIEWER_DEFAULT_PORT);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: vncviewer_main
*
* Description:
* VNC Viewer entry point. Connects to a VNC server and displays
* the remote framebuffer on the local LCD.
*
****************************************************************************/
int main(int argc, char *argv[])
{
const char *host = NULL;
const char *password = "";
uint16_t port = VNCVIEWER_DEFAULT_PORT;
int lcd_devno = VNCVIEWER_DEFAULT_LCD;
struct rfb_conn_s conn;
int opt;
int ret;
/* Parse command line arguments */
while ((opt = getopt(argc, argv, "p:d:h")) != -1)
{
switch (opt)
{
case 'p':
password = optarg;
break;
case 'd':
lcd_devno = atoi(optarg);
break;
case 'h':
show_usage(argv[0]);
return EXIT_SUCCESS;
default:
show_usage(argv[0]);
return EXIT_FAILURE;
}
}
if (optind < argc)
{
host = argv[optind++];
}
if (optind < argc)
{
port = atoi(argv[optind]);
}
if (host == NULL)
{
printf("vncviewer: host is required\n");
show_usage(argv[0]);
return EXIT_FAILURE;
}
/* Initialize LCD */
printf("vncviewer: initializing LCD...\n");
ret = lcd_init(&g_lcd, lcd_devno);
if (ret < 0)
{
printf("vncviewer: LCD init failed: %d\n", ret);
return EXIT_FAILURE;
}
/* Fill screen black */
lcd_fill(&g_lcd, COLOR_BLACK);
/* Connect to VNC server */
memset(&conn, 0, sizeof(conn));
/* Connection loop with retry */
for (; ; )
{
int rcvbuf;
conn.sockfd = rfb_connect(host, port);
if (conn.sockfd < 0)
{
printf("vncviewer: connection failed: %d, retrying...\n",
conn.sockfd);
sleep(2);
continue;
}
/* Increase TCP receive buffer to handle bursts */
rcvbuf = 32768;
setsockopt(conn.sockfd, SOL_SOCKET, SO_RCVBUF,
&rcvbuf, sizeof(rcvbuf));
/* RFB handshake */
ret = rfb_handshake(&conn, password);
if (ret < 0)
{
printf("vncviewer: handshake failed: %d, retrying...\n", ret);
close(conn.sockfd);
sleep(2);
continue;
}
/* Configure pixel format based on LCD */
ret = rfb_set_pixel_format(&conn, g_lcd.fmt);
if (ret < 0)
{
printf("vncviewer: set pixel format failed: %d, retrying...\n",
ret);
close(conn.sockfd);
sleep(2);
continue;
}
/* Set encodings: Raw only */
ret = rfb_set_encodings(&conn);
if (ret < 0)
{
printf("vncviewer: set encodings failed: %d, retrying...\n", ret);
close(conn.sockfd);
sleep(2);
continue;
}
/* Determine view size: min of server desktop and LCD */
conn.view_width = conn.fb_width < g_lcd.xres
? conn.fb_width : g_lcd.xres;
conn.view_height = conn.fb_height < g_lcd.yres
? conn.fb_height : g_lcd.yres;
printf("vncviewer: view area: %ux%u (server: %ux%u, lcd: %ux%u)\n",
conn.view_width, conn.view_height,
conn.fb_width, conn.fb_height,
g_lcd.xres, g_lcd.yres);
/* Request initial full framebuffer update */
ret = rfb_request_update(&conn, false,
0, 0, conn.view_width, conn.view_height);
if (ret < 0)
{
printf("vncviewer: initial update request failed: %d, "
"retrying...\n", ret);
close(conn.sockfd);
sleep(2);
continue;
}
/* Main loop: receive updates and render to LCD */
printf("vncviewer: entering main loop\n");
while (true)
{
/* Receive and process server message */
ret = rfb_recv_update(&conn, rect_callback, NULL);
if (ret < 0)
{
printf("vncviewer: recv error: %d\n", ret);
break;
}
/* Request next incremental update */
ret = rfb_request_update(&conn, true,
0, 0,
conn.view_width, conn.view_height);
if (ret < 0)
{
printf("vncviewer: update request failed: %d\n", ret);
break;
}
}
/* Connection lost - retry */
printf("vncviewer: reconnecting in 2 seconds...\n");
close(conn.sockfd);
sleep(2);
}
/* Cleanup */
printf("vncviewer: disconnecting\n");
close(conn.sockfd);
lcd_uninit(&g_lcd);
return EXIT_SUCCESS;
}