On Sun, Jul 23, 2023 at 09:16:40PM +0000, jon@elytron.openbsd.amsterdam wrote: > If I'm not mistaken, all wskbd_{get,set}_backlight uses are in the > following drivers: acpicbkbd, acpithinkpad, asmc, pwmleds, and now > my implementation in adb. It is my impression that they are roughly > the same code, I have collected them below to ease their inspection.
This doesn't look too bad actually but I am not quite sure about pwm. A common way to solve this is adding a task to do the heavy lifiting and then invoking that from interrupt context. In wskbd.c there is a wskbd_brightness_task() which you could use as a reference for a new wskbd_kbd_backlight_task(). > > I would also like to acknowledge the kind help of jcs@, whom I > approached back when I made my first post on this matter (before > the key shortcuts, wsconsctl only) upon coming across his acpicbkbd(4). > > (installed in dev/acpi/amsc.c:319) > > int > asmc_get_backlight(struct wskbd_backlight *kbl) > { > struct asmc_softc *sc = asmc_cd.cd_devs[0]; > > KASSERT(sc != NULL); > kbl->min = 0; > kbl->max = 0xff; > kbl->curval = sc->sc_backlight; > return 0; > } > > int > asmc_set_backlight(struct wskbd_backlight *kbl) > { > struct asmc_softc *sc = asmc_cd.cd_devs[0]; > > KASSERT(sc != NULL); > if (kbl->curval > 0xff) > return EINVAL; > sc->sc_backlight = kbl->curval; > task_add(systq, &sc->sc_task_backlight); > return 0; > } > > (installed in dev/acpi/acpicbkbd.c:94) > > int > acpicbkbd_get_backlight(struct wskbd_backlight *kbl) > { > struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0]; > > KASSERT(sc != NULL); > > kbl->min = 0; > kbl->max = ACPICBKBD_MAX_BACKLIGHT; > kbl->curval = sc->sc_backlight; > > return 0; > } > > int > acpicbkbd_set_backlight(struct wskbd_backlight *kbl) > { > struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0]; > > KASSERT(sc != NULL); > > if (kbl->curval > ACPICBKBD_MAX_BACKLIGHT) > return EINVAL; > > sc->sc_backlight = kbl->curval; > > acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0); > acpi_wakeup(sc->sc_acpi); > > return 0; > } > > (installed in dev/acpi/acpithinkpad.c:347) > > int > thinkpad_get_kbd_backlight(struct wskbd_backlight *kbl) > { > struct acpithinkpad_softc *sc = acpithinkpad_cd.cd_devs[0]; > > KASSERT(sc != NULL); > > kbl->min = 0; > kbl->max = (sc->sc_thinklight >> 8) & 0x0f; > kbl->curval = sc->sc_thinklight & 0x0f; > > if (kbl->max == 0) > return (ENOTTY); > > return 0; > } > > int > thinkpad_set_kbd_backlight(struct wskbd_backlight *kbl) > { > struct acpithinkpad_softc *sc = acpithinkpad_cd.cd_devs[0]; > int maxval; > > KASSERT(sc != NULL); > > maxval = (sc->sc_thinklight >> 8) & 0x0f; > > if (maxval == 0) > return (ENOTTY); > > if (kbl->curval > maxval) > return EINVAL; > > sc->sc_thinklight &= ~0xff; > sc->sc_thinklight |= kbl->curval; > acpi_addtask(sc->sc_acpi, thinkpad_set_thinklight, sc, 0); > acpi_wakeup(sc->sc_acpi); > return 0; > } > > (installed in pwmleds.c:102) > int > pwmleds_get_kbd_backlight(struct wskbd_backlight *kbl) > { > struct pwmleds_softc *sc; > struct pwm_state ps; > int error; > > sc = pwmleds_kbd_backlight(); > if (sc == NULL) > return ENOTTY; > > error = pwm_get_state(sc->sc_pwm, &ps); > if (error) > return error; > > kbl->min = 0; > kbl->max = sc->sc_max_brightness; > kbl->curval = (ps.ps_enabled) ? > ((uint64_t)ps.ps_pulse_width * kbl->max) / ps.ps_period : 0; > return 0; > } > > int > pwmleds_set_kbd_backlight(struct wskbd_backlight *kbl) > { > struct pwmleds_softc *sc; > struct pwm_state ps; > > sc = pwmleds_kbd_backlight(); > if (sc == NULL) > return ENOTTY; > > if (kbl->curval < 0 || kbl->curval > sc->sc_max_brightness) > return EINVAL; > > pwm_init_state(sc->sc_pwm, &ps); > ps.ps_pulse_width = > ((uint64_t)kbl->curval * ps.ps_period) / sc->sc_max_brightness; > ps.ps_enabled = (ps.ps_pulse_width > 0); > return pwm_set_state(sc->sc_pwm, &ps); > }