feat(rk3588s): blink AP display and package source tree

This commit is contained in:
2026-05-23 17:44:47 +08:00
parent 9eddc702b6
commit 5347a728da
1332 changed files with 377937 additions and 3 deletions

406
lib/resource/3588s/src/main.c Executable file
View File

@@ -0,0 +1,406 @@
#include "lvgl/lvgl.h"
#include "lv_drivers/display/fbdev.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define DISP_BUF_SIZE (320 * 240)
LV_IMG_DECLARE(logo);
/* ===================== UI Objects ===================== */
static lv_obj_t *hours_label;
static lv_obj_t *minutes_label;
static lv_obj_t *seconds_label;
static lv_obj_t *colon1_label;
static lv_obj_t *colon2_label;
static lv_obj_t *eth_ip_label;
static lv_obj_t *wifi_ip_label;
static lv_obj_t *custom_text_label;
static volatile bool show_custom_text = false;
static volatile bool custom_text_blink = false;
static volatile bool custom_text_visible = true;
static char custom_text_buf[256] = {0};
#define LVGL_CMD_FIFO "/tmp/lvgl_cmd"
#define LOGO_SHOW_SECONDS 5
/* ===================== Dark Theme ===================== */
static void apply_dark_theme(void)
{
lv_obj_t *scr = lv_disp_get_scr_act(NULL);
lv_obj_set_style_bg_color(scr, lv_color_black(), 0);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
}
/* ===================== Time UI ===================== */
static void create_time_labels(lv_obj_t *parent)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, &lv_font_montserrat_48);
lv_style_set_text_color(&style, lv_color_white());
hours_label = lv_label_create(parent);
minutes_label = lv_label_create(parent);
seconds_label = lv_label_create(parent);
colon1_label = lv_label_create(parent);
colon2_label = lv_label_create(parent);
lv_obj_add_style(hours_label, &style, 0);
lv_obj_add_style(minutes_label, &style, 0);
lv_obj_add_style(seconds_label, &style, 0);
lv_obj_add_style(colon1_label, &style, 0);
lv_obj_add_style(colon2_label, &style, 0);
lv_label_set_text(colon1_label, ":");
lv_label_set_text(colon2_label, ":");
lv_obj_align(hours_label, LV_ALIGN_CENTER, -80, -25);
lv_obj_align_to(colon1_label, hours_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_align_to(minutes_label, colon1_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_align_to(colon2_label, minutes_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_align_to(seconds_label, colon2_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_add_flag(hours_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(minutes_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(seconds_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(colon1_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(colon2_label, LV_OBJ_FLAG_HIDDEN);
}
static void update_time_labels(int h, int m, int s)
{
char buf[4];
snprintf(buf, sizeof(buf), "%02d", h);
lv_label_set_text(hours_label, buf);
snprintf(buf, sizeof(buf), "%02d", m);
lv_label_set_text(minutes_label, buf);
snprintf(buf, sizeof(buf), "%02d", s);
lv_label_set_text(seconds_label, buf);
lv_obj_align_to(colon1_label, hours_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_align_to(minutes_label, colon1_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_align_to(colon2_label, minutes_label, LV_ALIGN_OUT_RIGHT_MID, 6, 0);
lv_obj_align_to(seconds_label, colon2_label, LV_ALIGN_OUT_RIGHT_MID,6, 0);
}
static void create_custom_text_label(lv_obj_t *parent)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, &lv_font_montserrat_48);
lv_style_set_text_color(&style, lv_color_white());
custom_text_label = lv_label_create(parent);
lv_obj_add_style(custom_text_label, &style, 0);
lv_label_set_text(custom_text_label, "");
lv_obj_align(custom_text_label, LV_ALIGN_CENTER, 0, -25);
lv_obj_add_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
}
static void show_time_row(bool visible)
{
if(visible) {
lv_obj_clear_flag(hours_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(minutes_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(seconds_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(colon1_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(colon2_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_add_flag(hours_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(minutes_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(seconds_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(colon1_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(colon2_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
}
}
static void apply_show_text_async(void *arg)
{
const char *text = (const char *)arg;
show_custom_text = true;
custom_text_blink = false;
custom_text_visible = true;
lv_label_set_text(custom_text_label, text ? text : "");
lv_obj_align(custom_text_label, LV_ALIGN_CENTER, 0, -25);
show_time_row(false);
lv_obj_clear_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
}
static void apply_show_ap_async(void *arg)
{
(void)arg;
show_custom_text = true;
custom_text_blink = true;
custom_text_visible = true;
lv_label_set_text(custom_text_label, "AP");
lv_obj_align(custom_text_label, LV_ALIGN_CENTER, 0, -25);
show_time_row(false);
lv_obj_clear_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
}
static void apply_show_time_async(void *arg)
{
(void)arg;
show_custom_text = false;
custom_text_blink = false;
custom_text_visible = true;
show_time_row(true);
}
static void *fifo_thread(void *arg)
{
(void)arg;
unlink(LVGL_CMD_FIFO);
if (mkfifo(LVGL_CMD_FIFO, 0666) < 0 && errno != EEXIST) {
perror("mkfifo lvgl_cmd");
return NULL;
}
while (1) {
int fd = open(LVGL_CMD_FIFO, O_RDONLY);
if (fd < 0) {
usleep(200000);
continue;
}
FILE *fp = fdopen(fd, "r");
if (!fp) {
close(fd);
usleep(200000);
continue;
}
char line[256];
while (fgets(line, sizeof(line), fp)) {
size_t len = strlen(line);
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
line[--len] = '\0';
}
if (strncmp(line, "show_text:", 10) == 0) {
strncpy(custom_text_buf, line + 10, sizeof(custom_text_buf) - 1);
custom_text_buf[sizeof(custom_text_buf) - 1] = '\0';
if (strcmp(custom_text_buf, "AP") == 0) {
lv_async_call(apply_show_ap_async, NULL);
} else {
lv_async_call(apply_show_text_async, custom_text_buf);
}
} else if (strcmp(line, "show_time") == 0) {
lv_async_call(apply_show_time_async, NULL);
}
}
fclose(fp);
}
return NULL;
}
/* ===================== IP UI ===================== */
static void create_ip_labels(lv_obj_t *parent)
{
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, &lv_font_montserrat_20);
lv_style_set_text_color(&style, lv_color_white());
eth_ip_label = lv_label_create(parent);
wifi_ip_label = lv_label_create(parent);
lv_obj_add_style(eth_ip_label, &style, 0);
lv_obj_add_style(wifi_ip_label, &style, 0);
lv_label_set_text(eth_ip_label, "ETH : --");
lv_label_set_text(wifi_ip_label, "WiFi: --");
lv_obj_align(eth_ip_label, LV_ALIGN_CENTER, 0, 35);
lv_obj_align(wifi_ip_label, LV_ALIGN_CENTER, 0, 60);
lv_obj_add_flag(eth_ip_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(wifi_ip_label, LV_OBJ_FLAG_HIDDEN);
}
/* ===================== IP Logic ===================== */
static void get_ip(const char *ifname, char *out, size_t len)
{
struct ifaddrs *ifaddr, *ifa;
out[0] = 0;
if (getifaddrs(&ifaddr))
return;
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
continue;
if (ifa->ifa_addr->sa_family == AF_INET &&
strcmp(ifa->ifa_name, ifname) == 0) {
inet_ntop(AF_INET,
&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
out, len);
break;
}
}
freeifaddrs(ifaddr);
}
static void update_ip_ui(void)
{
char eth[32] = {0}, wifi[32] = {0};
get_ip("enP4p65s0", eth, sizeof(eth));
get_ip("wlan0", wifi, sizeof(wifi));
if (eth[0]) {
lv_label_set_text_fmt(eth_ip_label, "ETH : %s", eth);
} else {
lv_label_set_text(eth_ip_label, "ETH : Not Connected");
}
if (wifi[0]) {
lv_label_set_text_fmt(wifi_ip_label, "WiFi: %s", wifi);
} else {
lv_label_set_text(wifi_ip_label, "WiFi: Not Connected");
}
}
/* ===================== Netlink Thread ===================== */
static void *netlink_thread(void *arg)
{
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
struct sockaddr_nl addr = {
.nl_family = AF_NETLINK,
.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR,
};
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
char buf[4096];
while (1) {
recv(sock, buf, sizeof(buf), 0);
lv_async_call((lv_async_cb_t)update_ip_ui, NULL);
}
return NULL;
}
/* ===================== LVGL Tick ===================== */
uint32_t custom_tick_get(void)
{
static uint64_t start = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t now = tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
if (!start)
start = now;
return now - start;
}
/* ===================== Main ===================== */
int main(void)
{
lv_init();
fbdev_init();
static lv_color_t buf[DISP_BUF_SIZE];
static lv_disp_draw_buf_t draw_buf;
lv_disp_draw_buf_init(&draw_buf, buf, NULL, DISP_BUF_SIZE);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.draw_buf = &draw_buf;
disp_drv.flush_cb = fbdev_flush;
disp_drv.hor_res = 320;
disp_drv.ver_res = 240;
lv_disp_drv_register(&disp_drv);
apply_dark_theme();
lv_obj_t *scr = lv_disp_get_scr_act(NULL);
lv_obj_t *img = lv_img_create(scr);
lv_img_set_src(img, &logo);
lv_obj_center(img);
create_time_labels(scr);
create_custom_text_label(scr);
create_ip_labels(scr);
pthread_t tid;
pthread_create(&tid, NULL, netlink_thread, NULL);
pthread_detach(tid);
pthread_t fifo_tid;
pthread_create(&fifo_tid, NULL, fifo_thread, NULL);
pthread_detach(fifo_tid);
time_t start = time(NULL);
int last_sec = -1;
bool shown = false;
while (1) {
time_t now = time(NULL);
if (!shown && now - start >= LOGO_SHOW_SECONDS) {
lv_obj_add_flag(img, LV_OBJ_FLAG_HIDDEN);
show_time_row(true);
lv_obj_clear_flag(eth_ip_label, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(wifi_ip_label, LV_OBJ_FLAG_HIDDEN);
update_ip_ui();
shown = true;
}
struct tm *tm = localtime(&now);
if (!show_custom_text && tm->tm_sec != last_sec) {
update_time_labels(tm->tm_hour, tm->tm_min, tm->tm_sec);
last_sec = tm->tm_sec;
}
static uint32_t last_blink_ms = 0;
uint32_t now_ms = lv_tick_get();
if (custom_text_blink && now_ms - last_blink_ms >= 500) {
last_blink_ms = now_ms;
custom_text_visible = !custom_text_visible;
if (custom_text_visible) {
lv_obj_clear_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_add_flag(custom_text_label, LV_OBJ_FLAG_HIDDEN);
}
}
lv_timer_handler();
usleep(10000);
}
}