From 42e87b498c51c73d52cf8b5bd2f5e31f7a0e1bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 01:38:02 +0800 Subject: [PATCH] Brightness (Linux): allow specifying busno for ddcutil Ref: #580 --- src/detection/brightness/brightness_linux.c | 95 +++++++++++++++------ src/modules/brightness/brightness.c | 24 ++++++ src/modules/brightness/option.h | 4 + 3 files changed, 97 insertions(+), 26 deletions(-) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index d46599a85..ef622464b 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -92,18 +92,80 @@ static const char* detectWithBacklight(FFlist* result) #include +typedef struct DdcutilData +{ + FF_LIBRARY_SYMBOL(ddca_open_display2) + FF_LIBRARY_SYMBOL(ddca_get_any_vcp_value_using_explicit_type) + FF_LIBRARY_SYMBOL(ddca_free_any_vcp_value) + FF_LIBRARY_SYMBOL(ddca_close_display) +} DdcutilData; + +static void detectWithDdcciImpl(DdcutilData* data, FFlist* result, DDCA_Display_Info* dinfo) +{ + DDCA_Display_Handle handle; + if (data->ffddca_open_display2(dinfo->dref, false, &handle) >= 0) + { + DDCA_Any_Vcp_Value* vcpValue = NULL; + if (data->ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) + { + assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE); + int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue); + data->ffddca_free_any_vcp_value(vcpValue); + + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + brightness->max = max; + brightness->min = 0; + brightness->current = current; + ffStrbufInitS(&brightness->name, dinfo->model_name); + } + data->ffddca_close_display(handle); + } +} + static const char* detectWithDdcci(FFlist* result) { - FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5); + FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_create_busno_display_identifier) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_create_display_ref) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_display_identifier) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_display_ref) + + DdcutilData ddcutilData; + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_open_display2) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_get_any_vcp_value_using_explicit_type) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_free_any_vcp_value) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_close_display) libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330 + if (instance.config.brightness.busNos.length) + { + FF_SUPPRESS_IO(); + + FF_LIST_FOR_EACH(int, busno, instance.config.brightness.busNos) + { + DDCA_Display_Identifier did; + if (ffddca_create_busno_display_identifier(*busno, &did) >= 0) + { + DDCA_Display_Ref dref; + if (ffddca_create_display_ref(did, &dref) >= 0) + { + FF_AUTO_FREE DDCA_Display_Info* dinfo = NULL; + if (ffddca_get_display_info(dref, &dinfo) >= 0) + detectWithDdcciImpl(&ddcutilData, result, dinfo); + ffddca_free_display_ref(dref); + } + + ffddca_free_display_identifier(did); + } + } + + return NULL; + } + FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL; - if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0)) + if (ffddca_get_display_info_list2(false, &infoList) < 0) return "ddca_get_display_info_list2(false, &infoList) failed"; if (infoList->ct == 0) @@ -111,26 +173,7 @@ static const char* detectWithDdcci(FFlist* result) for (int index = 0; index < infoList->ct; ++index) { - const DDCA_Display_Info* display = &infoList->info[index]; - - DDCA_Display_Handle handle; - if (ffddca_open_display2(display->dref, false, &handle) >= 0) - { - DDCA_Any_Vcp_Value* vcpValue = NULL; - if (ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) - { - assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE); - int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue); - ffddca_free_any_vcp_value(vcpValue); - - FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->max = max; - brightness->min = 0; - brightness->current = current; - ffStrbufInitS(&brightness->name, display->model_name); - } - ffddca_close_display(handle); - } + detectWithDdcciImpl(&ddcutilData, result, &infoList->info[index]); } return NULL; diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index f65c30d21..2a737a9f9 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -88,6 +88,10 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson, ffPrintBrightnessHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); + + #ifdef __linux__ + ffListInit(&options->busNos, sizeof(int)); + #endif } bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value) @@ -103,6 +107,10 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); + + #ifdef __linux__ + ffListDestroy(&options->busNos); + #endif } void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module) @@ -118,6 +126,22 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + #ifdef __linux__ + if(ffStrEqualsIgnCase(key, "busNos")) + { + if (!yyjson_is_arr(val)) continue; + + yyjson_val* item; + size_t idx, max; + yyjson_arr_foreach(val, idx, max, item) + { + if (!yyjson_is_int(item)) continue; + *(int*) ffListAdd(&options->busNos) = yyjson_get_int(item); + } + continue; + } + #endif + ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index aa67ac190..bbaebef7d 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -8,4 +8,8 @@ typedef struct FFBrightnessOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + +#ifdef __linux__ + FFlist busNos; +#endif } FFBrightnessOptions;