report acpi video hot key event through input device
Signed-off-by: Luming Yu <[EMAIL PROTECTED]>
--
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 00d25b3..03d84db 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -31,6 +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 <asm/uaccess.h>
@@ -131,6 +132,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 {
@@ -1714,6 +1717,8 @@ static void acpi_video_bus_notify(acpi_h
{
struct acpi_video_bus *video = data;
struct acpi_device *device = NULL;
+ struct input_dev *input;
+ int keycode;
printk("video bus notify\n");
@@ -1721,11 +1726,13 @@ static void acpi_video_bus_notify(acpi_h
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_UNKNOWN;
break;
case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
@@ -1734,21 +1741,37 @@ static void acpi_video_bus_notify(acpi_h
acpi_video_device_rebind(video);
acpi_video_switch_output(video, event);
acpi_bus_generate_event(device, event, 0);
+ keycode = KEY_UNKNOWN;
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_UNKNOWN;
+ 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;
}
@@ -1756,30 +1779,60 @@ static void acpi_video_device_notify(acp
{
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_SWITCH: /* change in status (cycle output
device) */
case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device
status) */
acpi_bus_generate_event(device, event, 0);
+ keycode = KEY_UNKNOWN;
break;
case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
+ acpi_video_switch_brightness(video_device, event);
+ acpi_bus_generate_event(device, event, 0);
+ keycode = KEY_UNKNOWN;
+ 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_BRIGHTNESS_UP;
+ 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_BRIGHTNESS_DOWN;
+ 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_BRIGHTNESS_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;
}
@@ -1788,7 +1841,7 @@ static int acpi_video_bus_add(struct acp
int result = 0;
acpi_status status = 0;
struct acpi_video_bus *video = NULL;
-
+ struct input_dev *input;
if (!device)
return -EINVAL;
@@ -1830,7 +1883,18 @@ static int acpi_video_bus_add(struct acp
result = -ENODEV;
goto end;
}
-
+
+ video->input = input = input_allocate_device();
+
+ snprintf(video->phys, sizeof(video->phys),
+ "%s/video/input0", acpi_device_bid(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);
+ input_register_device(input);
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",
@@ -1863,7 +1927,7 @@ static int acpi_video_bus_remove(struct
acpi_video_bus_put_devices(video);
acpi_video_bus_remove_fs(device);
-
+ input_unregister_device(video->input);
kfree(video->attached_array);
kfree(video);
diff --git a/include/linux/input.h b/include/linux/input.h
index be2bf3a..2ccdb50 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -544,6 +544,13 @@ struct input_absinfo {
#define KEY_BRL_DOT7 0x1f7
#define KEY_BRL_DOT8 0x1f8
+#define KEY_VIDEO_NEXT 0x1f9
+#define KEY_VIDEO_PREV 0x1fa
+#define KEY_BRIGHTNESS_UP 0x1fb
+#define KEY_BRIGHTNESS_DOWN 0x1fc
+#define KEY_BRIGHTNESS_ZERO 0x1fd
+#define KEY_BRIGHTNESS_OFF 0x1fe
+
/* We avoid low common keys in module aliases so they don't get huge. */
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 00d25b3..03d84db 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -31,6 +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 <asm/uaccess.h>
@@ -131,6 +132,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 {
@@ -1714,6 +1717,8 @@ static void acpi_video_bus_notify(acpi_h
{
struct acpi_video_bus *video = data;
struct acpi_device *device = NULL;
+ struct input_dev *input;
+ int keycode;
printk("video bus notify\n");
@@ -1721,11 +1726,13 @@ static void acpi_video_bus_notify(acpi_h
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_UNKNOWN;
break;
case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
@@ -1734,21 +1741,37 @@ static void acpi_video_bus_notify(acpi_h
acpi_video_device_rebind(video);
acpi_video_switch_output(video, event);
acpi_bus_generate_event(device, event, 0);
+ keycode = KEY_UNKNOWN;
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_UNKNOWN;
+ 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;
}
@@ -1756,30 +1779,60 @@ static void acpi_video_device_notify(acp
{
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_SWITCH: /* change in status (cycle output device) */
case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
acpi_bus_generate_event(device, event, 0);
+ keycode = KEY_UNKNOWN;
break;
case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
+ acpi_video_switch_brightness(video_device, event);
+ acpi_bus_generate_event(device, event, 0);
+ keycode = KEY_UNKNOWN;
+ 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_BRIGHTNESS_UP;
+ 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_BRIGHTNESS_DOWN;
+ 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_BRIGHTNESS_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;
}
@@ -1788,7 +1841,7 @@ static int acpi_video_bus_add(struct acp
int result = 0;
acpi_status status = 0;
struct acpi_video_bus *video = NULL;
-
+ struct input_dev *input;
if (!device)
return -EINVAL;
@@ -1830,7 +1883,18 @@ static int acpi_video_bus_add(struct acp
result = -ENODEV;
goto end;
}
-
+
+ video->input = input = input_allocate_device();
+
+ snprintf(video->phys, sizeof(video->phys),
+ "%s/video/input0", acpi_device_bid(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);
+ input_register_device(input);
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",
@@ -1863,7 +1927,7 @@ static int acpi_video_bus_remove(struct
acpi_video_bus_put_devices(video);
acpi_video_bus_remove_fs(device);
-
+ input_unregister_device(video->input);
kfree(video->attached_array);
kfree(video);
diff --git a/include/linux/input.h b/include/linux/input.h
index be2bf3a..2ccdb50 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -544,6 +544,13 @@ struct input_absinfo {
#define KEY_BRL_DOT7 0x1f7
#define KEY_BRL_DOT8 0x1f8
+#define KEY_VIDEO_NEXT 0x1f9
+#define KEY_VIDEO_PREV 0x1fa
+#define KEY_BRIGHTNESS_UP 0x1fb
+#define KEY_BRIGHTNESS_DOWN 0x1fc
+#define KEY_BRIGHTNESS_ZERO 0x1fd
+#define KEY_BRIGHTNESS_OFF 0x1fe
+
/* We avoid low common keys in module aliases so they don't get huge. */
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff