--- src/rhd_acpi.c.orig 2009-10-06 07:36:07.000000000 -0400 +++ src/rhd_acpi.c 2009-10-28 22:07:59.000000000 -0400 @@ -47,6 +47,89 @@ #include "rhd_acpi.h" +#if defined(__FreeBSD__) || defined(__DragonFly__) + +#include +#include + +#define ACPI_VIDEO_LEVELS "hw.acpi.video.lcd0.levels" +#define ACPI_VIDEO_BRIGHTNESS "hw.acpi.video.lcd0.brightness" + +#define RHD_BL_NORMALIZE(x, y) ((x) * (RHD_BACKLIGHT_PROPERTY_MAX + 1) / (y)) +#define RHD_BL_ROUNDDOWN(x, y) (((x) / (y)) * (y)) + +/* + * Get/Set LCD backlight brightness via acpi_video(4). + */ +static Bool +rhdDoBacklight(struct rhdOutput *Output, Bool do_write, int *val) +{ + int *levels; + size_t len; + int level; + int max_levels, num_levels; + int d1, d2, max, min; + int lower, step; + int i; + RHDFUNC(Output); + + if (sysctlbyname(ACPI_VIDEO_LEVELS, NULL, &len, NULL, 0) != 0 || len == 0) + return FALSE; + levels = (int *)malloc(len); + if (levels == NULL) + return FALSE; + if (sysctlbyname(ACPI_VIDEO_LEVELS, levels, &len, NULL, 0) != 0) { + free(levels); + return FALSE; + } + + num_levels = len / sizeof(*levels); + for (i = 1, max = 0, min = 0; i < num_levels; i++) { + if (levels[i] < levels[min]) + min = i; + if (levels[i] > levels[max]) + max = i; + } + max_levels = levels[max] - levels[min] + 1; + step = RHD_BL_NORMALIZE(1, max_levels); + + if (do_write) { + if (*val >= RHD_BL_ROUNDDOWN(RHD_BACKLIGHT_PROPERTY_MAX, step)) { + level = levels[max]; + free(levels); + } else { + d1 = RHD_BACKLIGHT_PROPERTY_MAX; + lower = RHD_BL_ROUNDDOWN(*val, step); + for (i = 0; i < num_levels; i++) { + if (RHD_BL_NORMALIZE(levels[i], max_levels) >= lower) { + d2 = RHD_BL_NORMALIZE(levels[i], max_levels) - lower; + if (d1 > d2) { + level = levels[i]; + d1 = d2; + } + } + } + free(levels); + if (d1 >= RHD_BACKLIGHT_PROPERTY_MAX) + return FALSE; + } + if (sysctlbyname(ACPI_VIDEO_BRIGHTNESS, NULL, 0, &level, sizeof(level)) != 0) + return FALSE; + RHDDebug(Output->scrnIndex, "%s: Wrote value %i (ACPI %i)\n", __func__, *val, level); + } else { + free(levels); + len = sizeof(level); + if (sysctlbyname(ACPI_VIDEO_BRIGHTNESS, &level, &len, NULL, 0) != 0) + return FALSE; + *val = RHD_BL_NORMALIZE(level, max_levels) + step - 1; + RHDDebug(Output->scrnIndex, "%s: Read value %i (ACPI %i)\n", __func__, *val, level); + } + + return TRUE; +} + +#elif defined(__linux__) + #define ACPI_PATH "/sys/class/backlight" /* @@ -120,6 +203,7 @@ return FALSE; } +#endif /* * RhdACPIGetBacklightControl(): return backlight value in range 0..255; @@ -128,7 +212,7 @@ int RhdACPIGetBacklightControl(struct rhdOutput *Output) { -#ifdef __linux__ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) int ret; RHDFUNC(Output); if (rhdDoBacklight(Output, FALSE, &ret)) @@ -144,7 +228,7 @@ RhdACPISetBacklightControl(struct rhdOutput *Output, int val) { RHDFUNC(Output); -#ifdef __linux__ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) rhdDoBacklight(Output, TRUE, &val); #endif }