implement support for display brightness

commit 54e685ba9fef2b5fc1505ddc932e4fa3fe87ed68
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date:   Wed Aug 26 17:46:15 2026 -0700

    improvements

commit b442a51a71
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date:   Wed Aug 26 14:49:31 2026 -0700

    docker: add new build deps for android

commit 1e6370391e
Merge: b21181c 0681459
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date:   Wed Aug 26 14:37:15 2026 -0700

    Merge branch 'master' into brightness

commit b21181c675
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date:   Sun Aug 23 16:58:09 2026 -0700

    update display brightness - initial implementation
This commit is contained in:
itsmattkc committed 2026-08-26 17:50:12 -07:00
1 parent 7caf3a4d9e
commit c809ff73e7
30 files changed
+322 -67

No files matched your search

@@ -2,6 +2,7 @@ package com.mattkc.vanilla;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import android.view.WindowManager;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -56,4 +57,18 @@ public class VanillaActivity extends SDLActivity {
videoSurfaceTexture = null;
}
}
public static boolean setScreenBrightness(float brightness) {
final VanillaActivity activity = (VanillaActivity) mSingleton;
if (activity == null) {
return false;
}
activity.runOnUiThread(() -> {
WindowManager.LayoutParams attributes = activity.getWindow().getAttributes();
attributes.screenBrightness = Math.max(0.0f, Math.min(1.0f, brightness));
activity.getWindow().setAttributes(attributes);
});
return true;
}
}
@@ -1,15 +0,0 @@
#!/bin/sh
# Listen for power button presses, in which case quit Vanilla (which should in turn reboot the Switch)
DEV=/dev/input/event0
APP=vanilla
evtest "$DEV" 2>/dev/null | while read -r line; do
case "$line" in
*KEY_SLEEP*,\ value\ 1*)
pid="$(pidof "$APP" | awk '{print $1}')"
[ -n "$pid" ] && kill -TERM "$pid"
;;
esac
done
@@ -1,16 +0,0 @@
#!/bin/sh
# Listen for volume button presses, in which case increase/decrease volume in ALSA
DEV=/dev/input/event5
evtest "$DEV" 2>/dev/null | while read -r line; do
case "$line" in
*KEY_VOLUMEDOWN*,\ value\ 1*)
amixer sset 'x Speaker' 5%- >/dev/null
;;
*KEY_VOLUMEUP*,\ value\ 1*)
amixer sset 'x Speaker' 5%+ unmute >/dev/null
;;
esac
done
@@ -5,19 +5,6 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib/aarch64-linux-gnu/tegra:/usr/l
export DISPLAY=:0
export SDL_VIDEODRIVER=x11
# Listen for power button presses
/usr/bin/vanilla-nx-power-btn &
POWER_BTN_WATCHER_PID=$!
/usr/bin/vanilla-nx-volume-btn &
VOLUME_BTN_WATCHER_PID=$!
# Ensure watcher is closed
cleanup() {
kill "$POWER_BTN_WATCHER_PID" 2>/dev/null
kill "$VOLUME_BTN_WATCHER_PID" 2>/dev/null
}
trap cleanup EXIT
# Start X
X "$DISPLAY" -nolisten tcp vt1 &
X_PID=$!
@@ -7,7 +7,7 @@ BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
BR2_TARGET_GENERIC_ROOT_PASSWD="root"
# BR2_TARGET_GENERIC_GETTY is not set
# BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/nx/rootfs/"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/nx/rootfs/ $(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_VANILLA_PATH)/board/nx/post_build.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_IMAGEGZ=y
@@ -7,7 +7,7 @@ BR2_GLOBAL_PATCH_DIR="board/orangepi/orangepi-zero2w/patches $(BR2_EXTERNAL_VAN
BR2_TARGET_GENERIC_ISSUE="Welcome to Orangepi Zero2W"
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
# BR2_TARGET_GENERIC_GETTY is not set
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/ $(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/orangepi/common/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/post_build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="support/scripts/genimage.sh"
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BINARIES_DIR)/genimage.cfg"
@@ -8,7 +8,7 @@ BR2_TARGET_GENERIC_ISSUE="Welcome to Orangepi Zero3"
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
# BR2_TARGET_GENERIC_GETTY is not set
BR2_SYSTEM_DHCP="eth0"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/ $(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/orangepi/common/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/post_build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="support/scripts/genimage.sh"
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BINARIES_DIR)/genimage.cfg"
@@ -5,7 +5,7 @@ BR2_GLOBAL_PATCH_DIR="board/raspberrypi/patches"
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
# BR2_TARGET_GENERIC_GETTY is not set
#BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/rootfs"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/raspberrypi0w/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/post_build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/raspberrypi0w/post-image.sh"
BR2_LINUX_KERNEL=y
@@ -6,7 +6,7 @@ BR2_GLOBAL_PATCH_DIR="board/raspberrypi/patches"
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
# BR2_TARGET_GENERIC_GETTY is not set
#BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/rootfs"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/raspberrypi/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/post_build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/raspberrypi/post-image.sh"
BR2_LINUX_KERNEL=y
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
case "$1" in
up)
exec amixer -q sset 'x Speaker' 5%+ unmute
;;
down)
exec amixer -q sset 'x Speaker' 5%-
;;
*)
exit 2
;;
esac
+1 -1
View File
@@ -2,7 +2,7 @@ FROM docker.io/ubuntu:24.04@sha256:33ceb71981b602c1a7443a53469e4dba065f7503eab30
# Install build dependencies
RUN apt update && \
apt -y install wget unzip git openjdk-17-jdk make && \
apt -y install wget unzip git openjdk-17-jdk make autoconf automake libtool pkg-config && \
apt-get clean && \
apt-get autoremove --yes && \
rm -rf /var/lib/{apt,dpkg,cache,log}/
+4
View File
@@ -309,6 +309,10 @@ if (ANDROID)
endif()
if (LINUX)
list(APPEND VANILLA_GUI_SRC
ui/ui_sdl_linux.c
)
# Link with DRM if available
option(VANILLA_BUILD_USE_DRM "Enable DRM video output" ON)
if (VANILLA_BUILD_USE_DRM)
+6
View File
@@ -93,6 +93,9 @@ void vpi_config_save()
sprintf(buf, "%i", vpi_config.force_software_decode);
xmlTextWriterWriteElement(writer, BAD_CAST "swdec", BAD_CAST buf);
sprintf(buf, "%f", vpi_config.screen_brightness);
xmlTextWriterWriteElement(writer, BAD_CAST "brightness", BAD_CAST buf);
xmlTextWriterStartElement(writer, BAD_CAST "controls");
if (vpi_config.keymap) {
xmlTextWriterStartElement(writer, BAD_CAST "keys");
@@ -184,6 +187,7 @@ void vpi_config_init()
vpi_config_reset_default_controls_internal();
vpi_config.cursor_in_fullscreen = 0;
vpi_config.autoconnect = -1;
vpi_config.screen_brightness = 0.5f;
// Load from file
char config_fn[1024];
@@ -250,6 +254,8 @@ void vpi_config_init()
vpi_config.fullscreen = atoi((const char *) child->children->content);
} else if (!strcmp((const char *) child->name, "swdec")) {
vpi_config.force_software_decode = atoi((const char *) child->children->content);
} else if (!strcmp((const char *) child->name, "brightness")) {
vpi_config.screen_brightness = atof((const char *) child->children->content);
} else if (!strcmp((const char *) child->name, "controls")) {
xmlNodePtr section = child->children;
while(section){
+1
View File
@@ -33,6 +33,7 @@ typedef struct {
int fast_drm;
int force_software_decode;
int autoconnect;
float screen_brightness;
} vpi_config_t;
extern vpi_config_t vpi_config;
+8
View File
@@ -97,6 +97,14 @@ int SDL_main(int argc, const char **argv)
goto exit;
}
#ifndef ANDROID
// On Linux/Buildroot platforms like Raspberry Pi and Nintendo Switch, it
// is desirable for the brightness to be restored from config. On Android
// though, the brightness will be set externally so changing it here is
// probably not desirable.
vui_brightness_set(vui, vpi_config.screen_brightness);
#endif
vpi_menu_init(vui);
while (vui_update_sdl(vui)) {
+39
View File
@@ -13,6 +13,20 @@
#include "menu_main.h"
#include "platform.h"
#if defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)
#include <pthread.h>
#include <string.h>
// Calling system() is synchronous and causes a noticeable pause during
// gameplay. This allows us to thunk from a separate detached thread so it
// doesn't interrupt the main thread.
static void *run_volume_helper(void *command)
{
(void) system((const char *) command);
return NULL;
}
#endif
void vpi_mic_callback(void *userdata, const uint8_t *data, size_t len)
{
vanilla_send_audio(data, len);
@@ -80,6 +94,31 @@ void vpi_menu_action(vui_context_t *vui, vpi_extra_action_t action)
vpi_config.fullscreen = !vpi_config.fullscreen;
vpi_config_save();
vui_set_fullscreen(vui, vpi_config.fullscreen);
break;
}
case VPI_ACTION_VOLUME_UP:
case VPI_ACTION_VOLUME_DOWN:
{
#if defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)
// On some platforms (specifically our Buildroot platforms like the
// Raspberry Pi and Nintendo Switch), there's no built-in handler for
// the volume keys. So here we handle them ourselves.
const char *helper = "/usr/libexec/vanilla-volume";
if (access(helper, X_OK) == 0) {
const char *command = action == VPI_ACTION_VOLUME_UP
? "/usr/libexec/vanilla-volume up"
: "/usr/libexec/vanilla-volume down";
pthread_t thread;
int error = pthread_create(&thread, NULL, run_volume_helper, (void *) command);
if (error == 0) {
error = pthread_detach(thread);
}
if (error != 0) {
vpilog("Failed to start volume helper thread: %s\n", strerror(error));
}
}
#endif
break;
}
}
}
+2
View File
@@ -9,6 +9,8 @@ typedef enum {
VPI_ACTION_TOGGLE_RECORDING,
VPI_ACTION_DISCONNECT,
VPI_ACTION_TOGGLE_FULLSCREEN,
VPI_ACTION_VOLUME_UP,
VPI_ACTION_VOLUME_DOWN
} vpi_extra_action_t;
void vpi_menu_init(vui_context_t *vui);
+15
View File
@@ -1088,6 +1088,21 @@ void *vpi_event_loop(void *arg)
case VANILLA_EVENT_MIC:
vui_mic_enabled_set(vui, event.data[0]);
break;
case VANILLA_EVENT_BRIGHTNESS:
{
// Clamp to valid values from console
uint8_t value = CLAMP(event.data[0], 1, 5);
// Normalize to 0.0 - 1.0
// float b = value / 5.0f;
float b = (value - 1) / 4.0f;
if (b < 0.01f) b = 0.01f;
vpi_config.screen_brightness = b;
vpi_config_save();
vui_brightness_set(vui, b);
break;
}
}
vanilla_free_event(&event);
+7
View File
@@ -1041,3 +1041,10 @@ void vui_mic_callback_set(vui_context_t *ctx, vui_mic_callback_t callback, void
ctx->mic_callback = callback;
ctx->mic_callback_data = userdata;
}
void vui_brightness_set(vui_context_t *ctx, float brightness)
{
if (ctx->brightness_set_handler) {
ctx->brightness_set_handler(ctx, brightness, ctx->brightness_set_handler_data);
}
}
+5
View File
@@ -182,4 +182,9 @@ vui_power_state_t vui_power_state_get(vui_context_t *ctx, int *percent);
void vui_mic_enabled_set(vui_context_t *ctx, int enabled);
void vui_mic_callback_set(vui_context_t *ctx, vui_mic_callback_t callback, void *userdata);
/**
* Miscellaneous functions
*/
void vui_brightness_set(vui_context_t *ctx, float brightness); // Expects brightness between 0.0f and 1.0f
#endif // VANILLA_PI_UI_H
+3
View File
@@ -104,6 +104,7 @@ typedef int (*vui_font_height_handler_t)(vui_font_size_t size, void *userdata);
typedef void (*vui_text_open_handler_t)(vui_context_t *ctx, int textedit, int open, void *userdata);
typedef vui_power_state_t (*vui_power_state_handler_t)(vui_context_t *ctx, int *percent);
typedef void (*vui_audio_enabled_handler_t)(vui_context_t *ctx, int enabled, void *userdata);
typedef void (*vui_brightness_set_handler_t)(vui_context_t *ctx, float value, void *userdata);
typedef struct vui_context_t {
void *platform_data;
@@ -155,6 +156,8 @@ typedef struct vui_context_t {
void *audio_enabled_handler_data;
vui_bool_callback_t fullscreen_enabled_handler;
void *fullscreen_enabled_handler_data;
vui_brightness_set_handler_t brightness_set_handler;
void *brightness_set_handler_data;
int default_button_map[VPI_CONFIG_BUTTONMAP_SIZE];
int default_axis_map[VPI_CONFIG_AXISMAP_SIZE];
+33 -1
View File
@@ -49,6 +49,12 @@
#include "platform_nx_imu.h"
#endif
#if defined(ANDROID) || defined(__ANDROID__)
// TODO
#elif defined(__linux__)
#include "ui_sdl_linux.h"
#endif
#define MIN(a,b) (((a)<(b))?(a):(b))
#define PW_CHAR_SIZE 20
#define PW_CHAR_PAD 2
@@ -187,6 +193,10 @@ void init_gamepad(vui_context_t *ctx)
ctx->default_key_map[SDL_SCANCODE_F12] = VPI_ACTION_SCREENSHOT;
ctx->default_key_map[SDL_SCANCODE_F11] = VPI_ACTION_TOGGLE_FULLSCREEN;
ctx->default_key_map[SDL_SCANCODE_ESCAPE] = VPI_ACTION_DISCONNECT;
ctx->default_key_map[SDL_SCANCODE_SLEEP] = VPI_ACTION_DISCONNECT; // Nintendo Switch power button
ctx->default_key_map[SDL_SCANCODE_VOLUMEUP] = VPI_ACTION_VOLUME_UP;
ctx->default_key_map[SDL_SCANCODE_VOLUMEDOWN] = VPI_ACTION_VOLUME_DOWN;
}
void find_valid_controller(vui_sdl_context_t *sdl_ctx)
@@ -354,6 +364,26 @@ void vui_sdl_fullscreen_enabled_handler(vui_context_t *ctx, int enabled, void *u
SDL_ShowCursor(vpi_config.cursor_in_fullscreen || !enabled);
}
void vui_sdl_brightness_set_handler(vui_context_t *ctx, float brightness, void *userdata)
{
vui_sdl_context_t *sdl_ctx = (vui_sdl_context_t *) ctx->platform_data;
vpilog("SETTING BRIGHTNESS TO %.1f\n", brightness);
#if defined(ANDROID) || defined(__ANDROID__)
if (vui_sdl_android_set_brightness(brightness) == 0) {
return;
}
#elif defined(__linux__)
if (vui_sdl_linux_set_brightness(brightness) == 0) {
return;
}
#endif
// Fallback
SDL_SetWindowBrightness(sdl_ctx->window, brightness);
}
void vui_sdl_get_key_mapping_handler(vui_context_t *ctx, int vanilla_btn, void *userdata)
{
@@ -537,7 +567,7 @@ int vui_sdl_event_thread(void *data)
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
if (sdl_ctx->controller && ev.cdevice.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(sdl_ctx->controller))) {
if (sdl_ctx->controller && ev.cdevice.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(sdl_ctx->controller))) {
int btn_idx = ev.cbutton.button;
int vanilla_btn;
@@ -880,6 +910,8 @@ int vui_init_sdl(vui_context_t *ctx, int fullscreen)
ctx->fullscreen_enabled_handler = vui_sdl_fullscreen_enabled_handler;
ctx->brightness_set_handler = vui_sdl_brightness_set_handler;
if (TTF_Init()) {
vpilog("Failed to TTF_Init\n");
return -1;
+20 -1
View File
@@ -12,6 +12,7 @@ static jobject video_surface;
static jmethodID create_surface_method;
static jmethodID update_texture_method;
static jmethodID destroy_surface_method;
static jmethodID set_brightness_method;
static int handle_jni_exception(JNIEnv *env, const char *operation)
{
@@ -53,7 +54,8 @@ static int init_jni(JNIEnv *env)
create_surface_method = (*env)->GetStaticMethodID(env, video_class, "createVideoSurface", "(III)Landroid/view/Surface;");
update_texture_method = (*env)->GetStaticMethodID(env, video_class, "updateVideoSurfaceTexture", "()[F");
destroy_surface_method = (*env)->GetStaticMethodID(env, video_class, "destroyVideoSurface", "()V");
if (!create_surface_method || !update_texture_method || !destroy_surface_method ||
set_brightness_method = (*env)->GetStaticMethodID(env, video_class, "setScreenBrightness", "(F)Z");
if (!create_surface_method || !update_texture_method || !destroy_surface_method || !set_brightness_method ||
handle_jni_exception(env, "looking up video surface methods") < 0) {
(*env)->DeleteGlobalRef(env, video_class);
video_class = NULL;
@@ -69,6 +71,7 @@ static int init_jni(JNIEnv *env)
create_surface_method = NULL;
update_texture_method = NULL;
destroy_surface_method = NULL;
set_brightness_method = NULL;
return -1;
}
@@ -144,6 +147,21 @@ void *vui_sdl_android_get_video_surface(void)
return video_surface;
}
int vui_sdl_android_set_brightness(float brightness)
{
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
if (!env || init_jni(env) < 0) {
return -1;
}
jboolean dispatched = (*env)->CallStaticBooleanMethod(env, video_class, set_brightness_method,
(jfloat) brightness);
if (handle_jni_exception(env, "setting screen brightness") < 0) {
return -1;
}
return dispatched ? 0 : -1;
}
int vui_sdl_android_update_video_texture(float transform[16])
{
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
@@ -192,4 +210,5 @@ void vui_sdl_android_destroy_video_texture(void)
create_surface_method = NULL;
update_texture_method = NULL;
destroy_surface_method = NULL;
set_brightness_method = NULL;
}
+1
View File
@@ -8,5 +8,6 @@ int vui_sdl_android_create_video_texture(SDL_Renderer *renderer, int width,
void *vui_sdl_android_get_video_surface(void);
int vui_sdl_android_update_video_texture(float transform[16]);
void vui_sdl_android_destroy_video_texture(void);
int vui_sdl_android_set_brightness(float brightness);
#endif
+103
View File
@@ -0,0 +1,103 @@
#include "ui_sdl_linux.h"
#include <dirent.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include "ui_util.h"
#define VUI_LINUX_BACKLIGHT_ROOT "/sys/class/backlight"
#define VUI_LINUX_BACKLIGHT_DEFAULT "backlight"
#define VUI_LINUX_BACKLIGHT_PATH_SIZE 4096
static int vui_sdl_linux_set_backlight_device(const char *device, float brightness)
{
char path[VUI_LINUX_BACKLIGHT_PATH_SIZE];
unsigned int max_brightness;
unsigned int value;
int path_length;
int write_failed;
int close_failed;
FILE *file;
if (!isfinite(brightness)) {
errno = EINVAL;
return -1;
}
brightness = CLAMP(brightness, 0.0f, 1.0f);
// Attempt to read max_brightness information
path_length = snprintf(path, sizeof(path), "%s/%s/max_brightness", VUI_LINUX_BACKLIGHT_ROOT, device);
if (path_length < 0 || path_length >= (int) sizeof(path)) {
errno = ENAMETOOLONG;
return -1;
}
file = fopen(path, "r");
if (!file) {
return -1;
}
if (fscanf(file, "%u", &max_brightness) != 1 || !max_brightness) {
fclose(file);
errno = EINVAL;
return -1;
}
fclose(file);
// Now that we have max_brightness, attempt to set actual brightness to a percentage of max brightness
value = lroundf(brightness * max_brightness);
path_length = snprintf(path, sizeof(path), "%s/%s/brightness", VUI_LINUX_BACKLIGHT_ROOT, device);
if (path_length < 0 || path_length >= (int) sizeof(path)) {
errno = ENAMETOOLONG;
return -1;
}
file = fopen(path, "w");
if (!file) {
return -1;
}
write_failed = fprintf(file, "%u\n", value) < 0;
close_failed = fclose(file) != 0;
if (write_failed || close_failed) {
return -1;
}
return 0;
}
int vui_sdl_linux_set_brightness(float brightness)
{
DIR *directory;
struct dirent *entry;
// See if "backlight" device exists (should exist on Nintendo Switch)
if (access(VUI_LINUX_BACKLIGHT_ROOT "/" VUI_LINUX_BACKLIGHT_DEFAULT, F_OK) == 0) {
return vui_sdl_linux_set_backlight_device(VUI_LINUX_BACKLIGHT_DEFAULT, brightness);
}
// Otherwise, iterate over directory to find next best device to set brightness on
directory = opendir(VUI_LINUX_BACKLIGHT_ROOT);
if (!directory) {
return -1;
}
while ((entry = readdir(directory))) {
if (entry->d_name[0] == '.') {
continue;
}
if (vui_sdl_linux_set_backlight_device(entry->d_name, brightness) == 0) {
closedir(directory);
return 0;
}
}
closedir(directory);
return -1;
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef VANILLA_PI_UI_SDL_LINUX_H
#define VANILLA_PI_UI_SDL_LINUX_H
int vui_sdl_linux_set_brightness(float brightness);
#endif // VANILLA_PI_UI_SDL_LINUX_H
+2
View File
@@ -9,6 +9,8 @@ void vui_strncpy(char *dst, const char *src, size_t max_dst_size);
size_t vui_utf8_cp_len(const char *s);
char *vui_utf8_advance(char *s);
#define CLAMP(x, low, high) (((x) < (low)) ? (low) : ((x) > (high)) ? (high) : (x))
static inline int intmin(int a, int b) { return a < b ? a : b; }
static inline int intmax(int a, int b) { return a > b ? a : b; }
static inline int64_t int64min(int64_t a, int64_t b) { return a < b ? a : b; }
+31 -5
View File
@@ -60,7 +60,7 @@ void send_generic_response(int skt, CmdHeader *response)
void handle_generic_packet(gamepad_context_t *info, int skt, GenericPacket *request)
{
GenericCmdHeader *gen_cmd = &request->generic_cmd_header;
vanilla_log("magic: %x, flags: %x, service ID: %u, method ID: %u", gen_cmd->magic_0x7E, gen_cmd->flags, gen_cmd->service_id, gen_cmd->method_id);
// vanilla_log("magic: %x, flags: %x, service ID: %u, method ID: %u", gen_cmd->magic_0x7E, gen_cmd->flags, gen_cmd->service_id, gen_cmd->method_id);
// Prepare response
GenericPacket response;
@@ -170,13 +170,39 @@ void handle_generic_packet(gamepad_context_t *info, int skt, GenericPacket *requ
}
case METHOD_ID_PERIPHERAL_UPDATE_EEPROM:
{
vanilla_log("5,12 - index: %u, length: %u", response.payload[0], response.payload[1]);
response.generic_cmd_header.error_code = 0;
uint8_t index = request->payload[0];
uint8_t length = request->payload[1];
vanilla_log("5,12 - index: %u, length: %u", index, length);
uint16_t our_crc = crc16(request->payload + 2, length - 2);
uint16_t their_crc = le16toh(*(uint16_t *)(request->payload + 2 + length - 2));
if (our_crc != their_crc) {
// TODO: Report some kind of error to the console?
} else {
// Update our EEPROM
switch (index) {
case 0x10:
{
// Console wants to change our brightness
// vanilla_log("Change brightness to %x", request->payload[2]);
uint8_t b = request->payload[2];
push_event(info->event_loop, VANILLA_EVENT_BRIGHTNESS, &b, sizeof(b));
break;
}
default:
vanilla_log("Console attempted write to unknown EEPROM offset: 0x%x", index);
}
// Report success
response.generic_cmd_header.error_code = 0;
}
break;
}
case METHOD_ID_PERIPHERAL_SET_REMOCON:
{
vanilla_log("5,24 - str1: %s, str2: %s", response.payload, response.payload + 5);
vanilla_log("5,24 - str1: %s, str2: %s", request->payload, request->payload + 5);
response.generic_cmd_header.error_code = 0;
break;
}
@@ -227,7 +253,7 @@ void handle_time_packet(int skt, TimePacket *request)
void handle_command_packet(gamepad_context_t *info, int skt, CmdHeader *request)
{
vanilla_log("packet_type: %u, query_type: %u, payload_size: 0x%X", request->packet_type, request->query_type, request->payload_size);
// vanilla_log("packet_type: %u, query_type: %u, payload_size: 0x%X", request->packet_type, request->query_type, request->payload_size);
switch (request->packet_type)
{
case PACKET_TYPE_REQUEST:
-9
View File
@@ -20,15 +20,6 @@
#include "vanilla.h"
#include "util.h"
#if defined(_WIN32)
// Windows has no htobe32, and is always virtually little-endiam
#define htobe32(x) htonl(x)
#elif defined(__APPLE__)
// macOS has no htobe32
#include <libkern/OSByteOrder.h>
#define htobe32(x) OSSwapHostToBigInt32(x)
#endif // __APPLE__
typedef struct
{
unsigned magic : 4;
+2 -1
View File
@@ -74,7 +74,8 @@ enum VanillaEvent
VANILLA_EVENT_VIBRATE,
VANILLA_EVENT_SYNC,
VANILLA_EVENT_ERROR,
VANILLA_EVENT_MIC
VANILLA_EVENT_MIC,
VANILLA_EVENT_BRIGHTNESS
};
enum VanillaRegion