mirror of
https://github.com/opnsense/src.git
synced 2026-02-18 18:20:26 -05:00
acpi_asus_wmi(4): Improve keyboard backlight support.
- Fix maximal keyboard backlight level, Although Linux source code comment says that backlight level is encoded in 3 bits of data, actual code limits maximum level to 3. - Add backlight(9) support for keyboard - Turn off/on keyboard backlight on suspend/resume Sponsored by: Future Crew LLC MFC after: 1 month Reviewed by: mav Differential Revision: https://reviews.freebsd.org/D48983 (cherry picked from commit f134662a1a5726d78880385002a03b8fe68805f6)
This commit is contained in:
parent
6616f35456
commit
9b5f1a6cd6
3 changed files with 142 additions and 6 deletions
|
|
@ -23,7 +23,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd July 2, 2012
|
||||
.Dd March 25, 2024
|
||||
.Dt ACPI_ASUS_WMI 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -72,11 +72,19 @@ Number of other variables under the same sysctl branch are model-specific.
|
|||
Defaults for these variables can be set in
|
||||
.Xr sysctl.conf 5 ,
|
||||
which is parsed at boot-time.
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/dev/backlight/acpi_asus_wmi0" -compact
|
||||
.It Pa /dev/backlight/acpi_asus_wmi0
|
||||
Keyboard
|
||||
.Xr backlight 8
|
||||
device node.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr acpi 4 ,
|
||||
.Xr acpi_asus 4 ,
|
||||
.Xr acpi_video 4 ,
|
||||
.Xr sysctl.conf 5 ,
|
||||
.Xr backlight 8 ,
|
||||
.Xr devd 8 ,
|
||||
.Xr sysctl 8
|
||||
.Sh HISTORY
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@
|
|||
#include <dev/acpica/acpivar.h>
|
||||
#include "acpi_wmi_if.h"
|
||||
|
||||
#include <dev/backlight/backlight.h>
|
||||
#include "backlight_if.h"
|
||||
|
||||
#ifdef EVDEV_SUPPORT
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
|
|
@ -117,6 +120,8 @@ struct acpi_asus_wmi_softc {
|
|||
struct sysctl_oid *sysctl_tree;
|
||||
int dsts_id;
|
||||
int handle_keys;
|
||||
struct cdev *kbd_bkl;
|
||||
uint32_t kbd_bkl_level;
|
||||
#ifdef EVDEV_SUPPORT
|
||||
struct evdev_dev *evdev;
|
||||
#endif
|
||||
|
|
@ -345,6 +350,8 @@ static void acpi_asus_wmi_identify(driver_t *driver, device_t parent);
|
|||
static int acpi_asus_wmi_probe(device_t dev);
|
||||
static int acpi_asus_wmi_attach(device_t dev);
|
||||
static int acpi_asus_wmi_detach(device_t dev);
|
||||
static int acpi_asus_wmi_suspend(device_t dev);
|
||||
static int acpi_asus_wmi_resume(device_t dev);
|
||||
|
||||
static int acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id,
|
||||
|
|
@ -357,12 +364,26 @@ static int acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc,
|
|||
static int acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc,
|
||||
UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval);
|
||||
static void acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context);
|
||||
static int acpi_asus_wmi_backlight_update_status(device_t dev,
|
||||
struct backlight_props *props);
|
||||
static int acpi_asus_wmi_backlight_get_status(device_t dev,
|
||||
struct backlight_props *props);
|
||||
static int acpi_asus_wmi_backlight_get_info(device_t dev,
|
||||
struct backlight_info *info);
|
||||
|
||||
static device_method_t acpi_asus_wmi_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, acpi_asus_wmi_identify),
|
||||
DEVMETHOD(device_probe, acpi_asus_wmi_probe),
|
||||
DEVMETHOD(device_attach, acpi_asus_wmi_attach),
|
||||
DEVMETHOD(device_detach, acpi_asus_wmi_detach),
|
||||
DEVMETHOD(device_suspend, acpi_asus_wmi_suspend),
|
||||
DEVMETHOD(device_resume, acpi_asus_wmi_resume),
|
||||
|
||||
/* Backlight interface */
|
||||
DEVMETHOD(backlight_update_status, acpi_asus_wmi_backlight_update_status),
|
||||
DEVMETHOD(backlight_get_status, acpi_asus_wmi_backlight_get_status),
|
||||
DEVMETHOD(backlight_get_info, acpi_asus_wmi_backlight_get_info),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
|
@ -376,10 +397,35 @@ static driver_t acpi_asus_wmi_driver = {
|
|||
DRIVER_MODULE(acpi_asus_wmi, acpi_wmi, acpi_asus_wmi_driver, 0, 0);
|
||||
MODULE_DEPEND(acpi_asus_wmi, acpi_wmi, 1, 1, 1);
|
||||
MODULE_DEPEND(acpi_asus_wmi, acpi, 1, 1, 1);
|
||||
MODULE_DEPEND(acpi_asus_wmi, backlight, 1, 1, 1);
|
||||
#ifdef EVDEV_SUPPORT
|
||||
MODULE_DEPEND(acpi_asus_wmi, evdev, 1, 1, 1);
|
||||
#endif
|
||||
|
||||
static const uint32_t acpi_asus_wmi_backlight_levels[] = { 0, 33, 66, 100 };
|
||||
|
||||
static inline uint32_t
|
||||
devstate_to_kbd_bkl_level(UINT32 val)
|
||||
{
|
||||
return (acpi_asus_wmi_backlight_levels[val & 0x3]);
|
||||
}
|
||||
|
||||
static inline UINT32
|
||||
kbd_bkl_level_to_devstate(uint32_t bkl)
|
||||
{
|
||||
UINT32 val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nitems(acpi_asus_wmi_backlight_levels); i++) {
|
||||
if (bkl < acpi_asus_wmi_backlight_levels[i])
|
||||
break;
|
||||
}
|
||||
val = (i - 1) & 0x3;
|
||||
if (val != 0)
|
||||
val |= 0x80;
|
||||
return(val);
|
||||
}
|
||||
|
||||
static void
|
||||
acpi_asus_wmi_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
|
|
@ -418,6 +464,7 @@ acpi_asus_wmi_attach(device_t dev)
|
|||
struct acpi_asus_wmi_softc *sc;
|
||||
UINT32 val;
|
||||
int dev_id, i;
|
||||
bool have_kbd_bkl = false;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
|
||||
|
||||
|
|
@ -502,6 +549,10 @@ next:
|
|||
if (val == 0)
|
||||
continue;
|
||||
break;
|
||||
case ASUS_WMI_DEVID_KBD_BACKLIGHT:
|
||||
sc->kbd_bkl_level = devstate_to_kbd_bkl_level(val);
|
||||
have_kbd_bkl = true;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if ((val & ASUS_WMI_DSTS_PRESENCE_BIT) == 0)
|
||||
continue;
|
||||
|
|
@ -541,12 +592,22 @@ next:
|
|||
}
|
||||
|
||||
if (evdev_register(sc->evdev) != 0) {
|
||||
device_printf(dev, "Can not register evdev\n");
|
||||
acpi_asus_wmi_detach(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (have_kbd_bkl) {
|
||||
sc->kbd_bkl = backlight_register("acpi_asus_wmi", dev);
|
||||
if (sc->kbd_bkl == NULL) {
|
||||
device_printf(dev, "Can not register backlight\n");
|
||||
acpi_asus_wmi_detach(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -557,6 +618,9 @@ acpi_asus_wmi_detach(device_t dev)
|
|||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
|
||||
|
||||
if (sc->kbd_bkl != NULL)
|
||||
backlight_destroy(sc->kbd_bkl);
|
||||
|
||||
if (sc->notify_guid) {
|
||||
ACPI_WMI_REMOVE_EVENT_HANDLER(dev, sc->notify_guid);
|
||||
#ifdef EVDEV_SUPPORT
|
||||
|
|
@ -567,6 +631,34 @@ acpi_asus_wmi_detach(device_t dev)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_asus_wmi_suspend(device_t dev)
|
||||
{
|
||||
struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (sc->kbd_bkl != NULL) {
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
|
||||
acpi_wpi_asus_set_devstate(sc,
|
||||
ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, NULL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_asus_wmi_resume(device_t dev)
|
||||
{
|
||||
struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (sc->kbd_bkl != NULL) {
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
|
||||
acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT,
|
||||
kbd_bkl_level_to_devstate(sc->kbd_bkl_level), NULL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
|
|
@ -615,7 +707,7 @@ acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc *sc, int dev_id)
|
|||
val &= ASUS_WMI_DSTS_BRIGHTNESS_MASK;
|
||||
break;
|
||||
case ASUS_WMI_DEVID_KBD_BACKLIGHT:
|
||||
val &= 0x7;
|
||||
val &= 0x3;
|
||||
break;
|
||||
default:
|
||||
if (val & ASUS_WMI_DSTS_UNKNOWN_BIT)
|
||||
|
|
@ -636,7 +728,7 @@ acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id, int arg, in
|
|||
|
||||
switch(dev_id) {
|
||||
case ASUS_WMI_DEVID_KBD_BACKLIGHT:
|
||||
arg = min(0x7, arg);
|
||||
arg = min(0x3, arg);
|
||||
if (arg != 0)
|
||||
arg |= 0x80;
|
||||
break;
|
||||
|
|
@ -701,9 +793,9 @@ acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context)
|
|||
if (code == 0xc4 || code == 0xc5) {
|
||||
acpi_wpi_asus_get_devstate(sc,
|
||||
ASUS_WMI_DEVID_KBD_BACKLIGHT, &val);
|
||||
val &= 0x7;
|
||||
val &= 0x3;
|
||||
if (code == 0xc4) {
|
||||
if (val < 0x7)
|
||||
if (val < 0x3)
|
||||
val++;
|
||||
} else if (val > 0)
|
||||
val--;
|
||||
|
|
@ -711,6 +803,7 @@ acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context)
|
|||
val |= 0x80;
|
||||
acpi_wpi_asus_set_devstate(sc,
|
||||
ASUS_WMI_DEVID_KBD_BACKLIGHT, val, NULL);
|
||||
sc->kbd_bkl_level = devstate_to_kbd_bkl_level(val);
|
||||
}
|
||||
/* Touchpad control. */
|
||||
if (code == 0x6b) {
|
||||
|
|
@ -767,3 +860,38 @@ acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc,
|
|||
return (acpi_asus_wmi_evaluate_method(sc->wmi_dev,
|
||||
ASUS_WMI_METHODID_DEVS, dev_id, ctrl_param, retval));
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_asus_wmi_backlight_update_status(device_t dev, struct backlight_props
|
||||
*props)
|
||||
{
|
||||
struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
|
||||
|
||||
acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT,
|
||||
kbd_bkl_level_to_devstate(props->brightness), NULL);
|
||||
sc->kbd_bkl_level = props->brightness;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_asus_wmi_backlight_get_status(device_t dev, struct backlight_props *props)
|
||||
{
|
||||
struct acpi_asus_wmi_softc *sc = device_get_softc(dev);
|
||||
|
||||
props->brightness = sc->kbd_bkl_level;
|
||||
props->nlevels = nitems(acpi_asus_wmi_backlight_levels);
|
||||
memcpy(props->levels, acpi_asus_wmi_backlight_levels,
|
||||
sizeof(acpi_asus_wmi_backlight_levels));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_asus_wmi_backlight_get_info(device_t dev, struct backlight_info *info)
|
||||
{
|
||||
info->type = BACKLIGHT_TYPE_KEYBOARD;
|
||||
strlcpy(info->name, "ASUS Keyboard", BACKLIGHTMAXNAMELENGTH);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
KMOD= acpi_asus_wmi
|
||||
CFLAGS+=-I${SRCTOP}/sys/dev/acpi_support
|
||||
SRCS= acpi_asus_wmi.c opt_acpi.h acpi_if.h acpi_wmi_if.h device_if.h bus_if.h
|
||||
SRCS+= opt_evdev.h
|
||||
SRCS+= opt_evdev.h backlight_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
|
|
|||
Loading…
Reference in a new issue