On Mon, Jan 13, 2020 at 12:20:10PM +0100, Patrick Wildt wrote: > The problem is that the last two values are 67 and 100. If you go > 5% down, it's 95. The nearest will still be 100. The code then > realizes that it's the same level as before, and does nlevel--. > But nlevel-- is 99, and not 67, because nlevel is the value and > not the index of the bcl array. So in essence the change needed > is to decrease the index, not the value, and then look up the value. Disucssing this over dinner again, patrick and I independently came up with the very same diff below.
It makes acpivout_find_brightness() return an index instead a level for the selected brightness. Just works on my X230; I can go through every level with the function keys and verify with xbacklight(1) that I am indeed not skipping any of the 16 levels in either direction. OK? Index: acpivout.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v retrieving revision 1.16 diff -u -p -r1.16 acpivout.c --- acpivout.c 14 Dec 2019 10:57:48 -0000 1.16 +++ acpivout.c 14 Jan 2020 18:50:23 -0000 @@ -165,7 +165,7 @@ acpivout_brightness_cycle(struct acpivou void acpivout_brightness_step(struct acpivout_softc *sc, int dir) { - int level, nlevel; + int level, nindex; if (sc->sc_bcl_len == 0) return; @@ -173,17 +173,17 @@ acpivout_brightness_step(struct acpivout if (level == -1) return; - nlevel = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP)); - if (nlevel == level) { - if (dir == 1 && (nlevel + 1 < sc->sc_bcl_len)) - nlevel++; - else if (dir == -1 && (nlevel - 1 >= 0)) - nlevel--; + nindex = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP)); + if (sc->sc_bcl[nindex] == level) { + if (dir == 1 && (nindex + 1 < sc->sc_bcl_len)) + nindex++; + else if (dir == -1 && (nindex - 1 >= 0)) + nindex--; } - if (nlevel == level) + if (sc->sc_bcl[nindex] == level) return; - acpivout_set_brightness(sc, nlevel); + acpivout_set_brightness(sc, sc->sc_bcl[nindex]); } void @@ -219,14 +219,14 @@ acpivout_find_brightness(struct acpivout for (i = 0; i < sc->sc_bcl_len - 1; i++) { mid = sc->sc_bcl[i] + (sc->sc_bcl[i + 1] - sc->sc_bcl[i]) / 2; if (sc->sc_bcl[i] <= level && level <= mid) - return sc->sc_bcl[i]; + return i; if (mid < level && level <= sc->sc_bcl[i + 1]) - return sc->sc_bcl[i + 1]; + return i + 1; } if (level < sc->sc_bcl[0]) - return sc->sc_bcl[0]; + return 0; else - return sc->sc_bcl[i]; + return i; } void @@ -321,7 +321,7 @@ int acpivout_set_param(struct wsdisplay_param *dp) { struct acpivout_softc *sc = NULL; - int i, exact; + int i, nindex; switch (dp->param) { case WSDISPLAYIO_PARAM_BRIGHTNESS: @@ -335,8 +335,8 @@ acpivout_set_param(struct wsdisplay_para } if (sc != NULL && sc->sc_bcl_len != 0) { rw_enter_write(&sc->sc_acpi->sc_lck); - exact = acpivout_find_brightness(sc, dp->curval); - acpivout_set_brightness(sc, exact); + nindex = acpivout_find_brightness(sc, dp->curval); + acpivout_set_brightness(sc, sc->sc_bcl[nindex]); rw_exit_write(&sc->sc_acpi->sc_lck); return 0; }