Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9dab196 authored by Luming Yu's avatar Luming Yu Committed by Len Brown
Browse files

ACPI video hotkey: export missing ACPI video hotkey events via input layer



Signed-off-by: default avatarYu Luming <luming.yu@intel.com>
Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent a1eb96a2
Loading
Loading
Loading
Loading
+88 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

#include <linux/input.h>
#include <linux/backlight.h>
#include <linux/video_output.h>
#include <asm/uaccess.h>
@@ -138,6 +138,8 @@ struct acpi_video_bus {
	struct semaphore sem;
	struct list_head video_device_list;
	struct proc_dir_entry *dir;
	struct input_dev *input;
	char phys[32];	/* for input device */
};

struct acpi_video_device_flags {
@@ -1764,6 +1766,9 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
{
	struct acpi_video_bus *video = data;
	struct acpi_device *device = NULL;
	struct input_dev *input;
	int keycode;


	printk("video bus notify\n");

@@ -1771,11 +1776,13 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
		return;

	device = video->device;
	input = video->input;

	switch (event) {
	case ACPI_VIDEO_NOTIFY_SWITCH:	/* User requested a switch,
					 * most likely via hotkey. */
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_SWITCHVIDEOMODE;
		break;

	case ACPI_VIDEO_NOTIFY_PROBE:	/* User plugged in or removed a video
@@ -1784,21 +1791,37 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
		acpi_video_device_rebind(video);
		acpi_video_switch_output(video, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_SWITCHVIDEOMODE;
		break;

	case ACPI_VIDEO_NOTIFY_CYCLE:	/* Cycle Display output hotkey pressed. */
		acpi_video_switch_output(video, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_SWITCHVIDEOMODE;
		break;
	case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:	/* Next Display output hotkey pressed. */
		acpi_video_switch_output(video, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_VIDEO_NEXT;
		break;
	case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:	/* previous Display output hotkey pressed. */
		acpi_video_switch_output(video, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_VIDEO_PREV;
		break;

	default:
		keycode = KEY_UNKNOWN;
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Unsupported event [0x%x]\n", event));
		break;
	}

	input_report_key(input, keycode, 1);
	input_sync(input);
	input_report_key(input, keycode, 0);
	input_sync(input);

	return;
}

@@ -1806,26 +1829,55 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
{
	struct acpi_video_device *video_device = data;
	struct acpi_device *device = NULL;
	struct acpi_video_bus *bus;
	struct input_dev *input;
	int keycode;

	if (!video_device)
		return;

	device = video_device->dev;
	bus = video_device->video;
	input = bus->input;

	switch (event) {
	case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:	/* Cycle brightness */
		acpi_video_switch_brightness(video_device, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_BRIGHTNESS_CYCLE;
		break;
	case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:	/* Increase brightness */
		acpi_video_switch_brightness(video_device, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_BRIGHTNESSUP;
		break;
	case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:	/* Decrease brightness */
		acpi_video_switch_brightness(video_device, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_BRIGHTNESSDOWN;
		break;
	case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:	/* zero brightnesss */
		acpi_video_switch_brightness(video_device, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_BRIGHTNESS_ZERO;
		break;
	case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:	/* display device off */
		acpi_video_switch_brightness(video_device, event);
		acpi_bus_generate_event(device, event, 0);
		keycode = KEY_DISPLAY_OFF;
		break;
	default:
		keycode = KEY_UNKNOWN;
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Unsupported event [0x%x]\n", event));
		break;
	}

	input_report_key(input, keycode, 1);
	input_sync(input);
	input_report_key(input, keycode, 0);
	input_sync(input);

	return;
}

@@ -1834,6 +1886,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
	int result = 0;
	acpi_status status = 0;
	struct acpi_video_bus *video = NULL;
	struct input_dev *input;


	if (!device)
@@ -1877,6 +1930,39 @@ static int acpi_video_bus_add(struct acpi_device *device)
		goto end;
	}


	video->input = input = input_allocate_device();

	snprintf(video->phys, sizeof(video->phys),
		"%s/video/input0", acpi_device_hid(video->device));

	input->name = acpi_device_name(video->device);
	input->phys = video->phys;
	input->id.bustype = BUS_HOST;
	input->id.product = 0x06;
	input->evbit[0] = BIT(EV_KEY);
	set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
	set_bit(KEY_VIDEO_NEXT, input->keybit);
	set_bit(KEY_VIDEO_PREV, input->keybit);
	set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
	set_bit(KEY_BRIGHTNESSUP, input->keybit);
	set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
	set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
	set_bit(KEY_DISPLAY_OFF, input->keybit);
	set_bit(KEY_UNKNOWN, input->keybit);
	result = input_register_device(input);
	if (result) {
		acpi_remove_notify_handler(video->device->handle,
						ACPI_DEVICE_NOTIFY,
						acpi_video_bus_notify);
		acpi_video_bus_stop_devices(video);
		acpi_video_bus_put_devices(video);
		kfree(video->attached_array);
		acpi_video_bus_remove_fs(device);
		goto end;
        }


	printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
	       ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
	       video->flags.multihead ? "yes" : "no",
@@ -1910,6 +1996,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
	acpi_video_bus_put_devices(video);
	acpi_video_bus_remove_fs(device);

	input_unregister_device(video->input);
	kfree(video->attached_array);
	kfree(video);