Author: wulf Date: Sat Oct 31 20:25:55 2020 New Revision: 367233 URL: https://svnweb.freebsd.org/changeset/base/367233
Log: acpi_video(4): Add evdev support for reporting of video events. Modified: head/sys/dev/acpica/acpi_video.c Modified: head/sys/dev/acpica/acpi_video.c ============================================================================== --- head/sys/dev/acpica/acpi_video.c Sat Oct 31 20:14:28 2020 (r367232) +++ head/sys/dev/acpica/acpi_video.c Sat Oct 31 20:25:55 2020 (r367233) @@ -29,6 +29,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_evdev.h" + #include <sys/param.h> #include <sys/bus.h> #include <sys/eventhandler.h> @@ -43,6 +45,11 @@ __FBSDID("$FreeBSD$"); #include <dev/acpica/acpivar.h> +#ifdef EVDEV_SUPPORT +#include <dev/evdev/input.h> +#include <dev/evdev/evdev.h> +#endif + /* ACPI video extension driver. */ struct acpi_video_output { ACPI_HANDLE handle; @@ -61,6 +68,9 @@ struct acpi_video_output { int *vo_levels; struct sysctl_ctx_list vo_sysctl_ctx; struct sysctl_oid *vo_sysctl_tree; +#ifdef EVDEV_SUPPORT + struct evdev_dev *evdev; +#endif }; STAILQ_HEAD(acpi_video_output_queue, acpi_video_output); @@ -70,6 +80,9 @@ struct acpi_video_softc { ACPI_HANDLE handle; struct acpi_video_output_queue vid_outputs; eventhandler_tag vid_pwr_evh; +#ifdef EVDEV_SUPPORT + struct evdev_dev *evdev; +#endif }; /* interfaces */ @@ -107,10 +120,14 @@ static void vo_set_device_state(ACPI_HANDLE, UINT32); /* events */ #define VID_NOTIFY_SWITCHED 0x80 #define VID_NOTIFY_REPROBE 0x81 +#define VID_NOTIFY_CYCLE_OUT 0x82 +#define VID_NOTIFY_NEXT_OUT 0x83 +#define VID_NOTIFY_PREV_OUT 0x84 #define VID_NOTIFY_CYCLE_BRN 0x85 #define VID_NOTIFY_INC_BRN 0x86 #define VID_NOTIFY_DEC_BRN 0x87 #define VID_NOTIFY_ZERO_BRN 0x88 +#define VID_NOTIFY_DISP_OFF 0x89 /* _DOS (Enable/Disable Output Switching) argument bits */ #define DOS_SWITCH_MASK 3 @@ -175,6 +192,9 @@ static devclass_t acpi_video_devclass; DRIVER_MODULE(acpi_video, vgapci, acpi_video_driver, acpi_video_devclass, acpi_video_modevent, NULL); MODULE_DEPEND(acpi_video, acpi, 1, 1, 1); +#ifdef EVDEV_SUPPORT +MODULE_DEPEND(acpi_video, evdev, 1, 1, 1); +#endif static struct sysctl_ctx_list acpi_video_sysctl_ctx; static struct sysctl_oid *acpi_video_sysctl_tree; @@ -190,6 +210,45 @@ ACPI_SERIAL_DECL(video, "ACPI video"); ACPI_SERIAL_DECL(video_output, "ACPI video output"); static MALLOC_DEFINE(M_ACPIVIDEO, "acpivideo", "ACPI video extension"); +#ifdef EVDEV_SUPPORT +static const struct { + UINT32 notify; + uint16_t key; +} acpi_video_evdev_map[] = { + { VID_NOTIFY_SWITCHED, KEY_SWITCHVIDEOMODE }, + { VID_NOTIFY_REPROBE, KEY_SWITCHVIDEOMODE }, + { VID_NOTIFY_CYCLE_OUT, KEY_SWITCHVIDEOMODE }, + { VID_NOTIFY_NEXT_OUT, KEY_VIDEO_NEXT }, + { VID_NOTIFY_PREV_OUT, KEY_VIDEO_PREV }, + { VID_NOTIFY_CYCLE_BRN, KEY_BRIGHTNESS_CYCLE }, + { VID_NOTIFY_INC_BRN, KEY_BRIGHTNESSUP }, + { VID_NOTIFY_DEC_BRN, KEY_BRIGHTNESSDOWN }, + { VID_NOTIFY_ZERO_BRN, KEY_BRIGHTNESS_ZERO }, + { VID_NOTIFY_DISP_OFF, KEY_DISPLAY_OFF }, +}; + +static void +acpi_video_push_evdev_event(struct evdev_dev *evdev, UINT32 notify) +{ + int i; + uint16_t key; + + /* Do not allow to execute 2 instances this routine concurently */ + ACPI_SERIAL_ASSERT(video_output); + + for (i = 0; i < nitems(acpi_video_evdev_map); i++) { + if (acpi_video_evdev_map[i].notify == notify) { + key = acpi_video_evdev_map[i].key; + evdev_push_key(evdev, key, 1); + evdev_sync(evdev); + evdev_push_key(evdev, key, 0); + evdev_sync(evdev); + break; + } + } +} +#endif + static int acpi_video_modevent(struct module *mod __unused, int evt, void *cookie __unused) { @@ -247,12 +306,30 @@ acpi_video_attach(device_t dev) { struct acpi_softc *acpi_sc; struct acpi_video_softc *sc; +#ifdef EVDEV_SUPPORT + int i; +#endif sc = device_get_softc(dev); acpi_sc = devclass_get_softc(devclass_find("acpi"), 0); if (acpi_sc == NULL) return (ENXIO); + +#ifdef EVDEV_SUPPORT + sc->evdev = evdev_alloc(); + evdev_set_name(sc->evdev, device_get_desc(dev)); + evdev_set_phys(sc->evdev, device_get_nameunit(dev)); + evdev_set_id(sc->evdev, BUS_HOST, 0, 0, 1); + evdev_support_event(sc->evdev, EV_SYN); + evdev_support_event(sc->evdev, EV_KEY); + for (i = 0; i < nitems(acpi_video_evdev_map); i++) + evdev_support_key(sc->evdev, acpi_video_evdev_map[i].key); + + if (evdev_register(sc->evdev) != 0) + return (ENXIO); +#endif + ACPI_SERIAL_BEGIN(video); if (acpi_video_sysctl_tree == NULL) { acpi_video_sysctl_tree = SYSCTL_ADD_NODE(&acpi_video_sysctl_ctx, @@ -306,6 +383,10 @@ acpi_video_detach(device_t dev) } ACPI_SERIAL_END(video); +#ifdef EVDEV_SUPPORT + evdev_free(sc->evdev); +#endif + return (0); } @@ -404,12 +485,21 @@ acpi_video_notify_handler(ACPI_HANDLE handle, UINT32 n } ACPI_SERIAL_END(video); break; + /* Next events should not appear if DOS_SWITCH_BY_OSPM policy is set */ + case VID_NOTIFY_CYCLE_OUT: + case VID_NOTIFY_NEXT_OUT: + case VID_NOTIFY_PREV_OUT: default: device_printf(sc->device, "unknown notify event 0x%x\n", notify); } AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_video_invoke_event_handler, (void *)(uintptr_t)notify); +#ifdef EVDEV_SUPPORT + ACPI_SERIAL_BEGIN(video_output); + acpi_video_push_evdev_event(sc->evdev, notify); + ACPI_SERIAL_END(video_output); +#endif } static void @@ -454,6 +544,9 @@ acpi_video_bind_outputs_subr(ACPI_HANDLE handle, UINT3 } vo = acpi_video_vo_init(adr); if (vo != NULL) { +#ifdef EVDEV_SUPPORT + vo->evdev = sc->evdev; +#endif acpi_video_vo_bind(vo, handle); STAILQ_INSERT_TAIL(&sc->vid_outputs, vo, vo_next); } @@ -708,6 +801,7 @@ acpi_video_vo_notify_handler(ACPI_HANDLE handle, UINT3 case VID_NOTIFY_INC_BRN: case VID_NOTIFY_DEC_BRN: case VID_NOTIFY_ZERO_BRN: + case VID_NOTIFY_DISP_OFF: if (vo->vo_levels == NULL) goto out; level = vo_get_brightness(vo); @@ -757,6 +851,9 @@ acpi_video_vo_notify_handler(ACPI_HANDLE handle, UINT3 vo_set_brightness(vo, new_level); vo->vo_brightness = new_level; } +#ifdef EVDEV_SUPPORT + acpi_video_push_evdev_event(vo->evdev, notify); +#endif out: ACPI_SERIAL_END(video_output); _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"