diff options
-rw-r--r-- | drivers/acpi/video.c | 91 | ||||
-rw-r--r-- | include/linux/input.h | 6 |
2 files changed, 93 insertions, 4 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d98701941981..d727d2c715df 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | 34 | #include <linux/input.h> | |
35 | #include <linux/backlight.h> | 35 | #include <linux/backlight.h> |
36 | #include <linux/video_output.h> | 36 | #include <linux/video_output.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -138,6 +138,8 @@ struct acpi_video_bus { | |||
138 | struct semaphore sem; | 138 | struct semaphore sem; |
139 | struct list_head video_device_list; | 139 | struct list_head video_device_list; |
140 | struct proc_dir_entry *dir; | 140 | struct proc_dir_entry *dir; |
141 | struct input_dev *input; | ||
142 | char phys[32]; /* for input device */ | ||
141 | }; | 143 | }; |
142 | 144 | ||
143 | struct acpi_video_device_flags { | 145 | struct acpi_video_device_flags { |
@@ -1764,6 +1766,9 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1764 | { | 1766 | { |
1765 | struct acpi_video_bus *video = data; | 1767 | struct acpi_video_bus *video = data; |
1766 | struct acpi_device *device = NULL; | 1768 | struct acpi_device *device = NULL; |
1769 | struct input_dev *input; | ||
1770 | int keycode; | ||
1771 | |||
1767 | 1772 | ||
1768 | printk("video bus notify\n"); | 1773 | printk("video bus notify\n"); |
1769 | 1774 | ||
@@ -1771,11 +1776,13 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1771 | return; | 1776 | return; |
1772 | 1777 | ||
1773 | device = video->device; | 1778 | device = video->device; |
1779 | input = video->input; | ||
1774 | 1780 | ||
1775 | switch (event) { | 1781 | switch (event) { |
1776 | case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, | 1782 | case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, |
1777 | * most likely via hotkey. */ | 1783 | * most likely via hotkey. */ |
1778 | acpi_bus_generate_event(device, event, 0); | 1784 | acpi_bus_generate_event(device, event, 0); |
1785 | keycode = KEY_SWITCHVIDEOMODE; | ||
1779 | break; | 1786 | break; |
1780 | 1787 | ||
1781 | case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video | 1788 | 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) | |||
1784 | acpi_video_device_rebind(video); | 1791 | acpi_video_device_rebind(video); |
1785 | acpi_video_switch_output(video, event); | 1792 | acpi_video_switch_output(video, event); |
1786 | acpi_bus_generate_event(device, event, 0); | 1793 | acpi_bus_generate_event(device, event, 0); |
1794 | keycode = KEY_SWITCHVIDEOMODE; | ||
1787 | break; | 1795 | break; |
1788 | 1796 | ||
1789 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ | 1797 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ |
1798 | acpi_video_switch_output(video, event); | ||
1799 | acpi_bus_generate_event(device, event, 0); | ||
1800 | keycode = KEY_SWITCHVIDEOMODE; | ||
1801 | break; | ||
1790 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ | 1802 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ |
1803 | acpi_video_switch_output(video, event); | ||
1804 | acpi_bus_generate_event(device, event, 0); | ||
1805 | keycode = KEY_VIDEO_NEXT; | ||
1806 | break; | ||
1791 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ | 1807 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ |
1792 | acpi_video_switch_output(video, event); | 1808 | acpi_video_switch_output(video, event); |
1793 | acpi_bus_generate_event(device, event, 0); | 1809 | acpi_bus_generate_event(device, event, 0); |
1810 | keycode = KEY_VIDEO_PREV; | ||
1794 | break; | 1811 | break; |
1795 | 1812 | ||
1796 | default: | 1813 | default: |
1814 | keycode = KEY_UNKNOWN; | ||
1797 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1815 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1798 | "Unsupported event [0x%x]\n", event)); | 1816 | "Unsupported event [0x%x]\n", event)); |
1799 | break; | 1817 | break; |
1800 | } | 1818 | } |
1801 | 1819 | ||
1820 | input_report_key(input, keycode, 1); | ||
1821 | input_sync(input); | ||
1822 | input_report_key(input, keycode, 0); | ||
1823 | input_sync(input); | ||
1824 | |||
1802 | return; | 1825 | return; |
1803 | } | 1826 | } |
1804 | 1827 | ||
@@ -1806,30 +1829,55 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1806 | { | 1829 | { |
1807 | struct acpi_video_device *video_device = data; | 1830 | struct acpi_video_device *video_device = data; |
1808 | struct acpi_device *device = NULL; | 1831 | struct acpi_device *device = NULL; |
1832 | struct acpi_video_bus *bus; | ||
1833 | struct input_dev *input; | ||
1834 | int keycode; | ||
1809 | 1835 | ||
1810 | if (!video_device) | 1836 | if (!video_device) |
1811 | return; | 1837 | return; |
1812 | 1838 | ||
1813 | device = video_device->dev; | 1839 | device = video_device->dev; |
1840 | bus = video_device->video; | ||
1841 | input = bus->input; | ||
1814 | 1842 | ||
1815 | switch (event) { | 1843 | switch (event) { |
1816 | case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */ | 1844 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ |
1817 | case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */ | 1845 | acpi_video_switch_brightness(video_device, event); |
1818 | acpi_bus_generate_event(device, event, 0); | 1846 | acpi_bus_generate_event(device, event, 0); |
1847 | keycode = KEY_BRIGHTNESS_CYCLE; | ||
1819 | break; | 1848 | break; |
1820 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ | ||
1821 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ | 1849 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ |
1850 | acpi_video_switch_brightness(video_device, event); | ||
1851 | acpi_bus_generate_event(device, event, 0); | ||
1852 | keycode = KEY_BRIGHTNESSUP; | ||
1853 | break; | ||
1822 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ | 1854 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ |
1855 | acpi_video_switch_brightness(video_device, event); | ||
1856 | acpi_bus_generate_event(device, event, 0); | ||
1857 | keycode = KEY_BRIGHTNESSDOWN; | ||
1858 | break; | ||
1823 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ | 1859 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ |
1860 | acpi_video_switch_brightness(video_device, event); | ||
1861 | acpi_bus_generate_event(device, event, 0); | ||
1862 | keycode = KEY_BRIGHTNESS_ZERO; | ||
1863 | break; | ||
1824 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ | 1864 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ |
1825 | acpi_video_switch_brightness(video_device, event); | 1865 | acpi_video_switch_brightness(video_device, event); |
1826 | acpi_bus_generate_event(device, event, 0); | 1866 | acpi_bus_generate_event(device, event, 0); |
1867 | keycode = KEY_DISPLAY_OFF; | ||
1827 | break; | 1868 | break; |
1828 | default: | 1869 | default: |
1870 | keycode = KEY_UNKNOWN; | ||
1829 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1871 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1830 | "Unsupported event [0x%x]\n", event)); | 1872 | "Unsupported event [0x%x]\n", event)); |
1831 | break; | 1873 | break; |
1832 | } | 1874 | } |
1875 | |||
1876 | input_report_key(input, keycode, 1); | ||
1877 | input_sync(input); | ||
1878 | input_report_key(input, keycode, 0); | ||
1879 | input_sync(input); | ||
1880 | |||
1833 | return; | 1881 | return; |
1834 | } | 1882 | } |
1835 | 1883 | ||
@@ -1838,6 +1886,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1838 | int result = 0; | 1886 | int result = 0; |
1839 | acpi_status status = 0; | 1887 | acpi_status status = 0; |
1840 | struct acpi_video_bus *video = NULL; | 1888 | struct acpi_video_bus *video = NULL; |
1889 | struct input_dev *input; | ||
1841 | 1890 | ||
1842 | 1891 | ||
1843 | if (!device) | 1892 | if (!device) |
@@ -1881,6 +1930,39 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1881 | goto end; | 1930 | goto end; |
1882 | } | 1931 | } |
1883 | 1932 | ||
1933 | |||
1934 | video->input = input = input_allocate_device(); | ||
1935 | |||
1936 | snprintf(video->phys, sizeof(video->phys), | ||
1937 | "%s/video/input0", acpi_device_hid(video->device)); | ||
1938 | |||
1939 | input->name = acpi_device_name(video->device); | ||
1940 | input->phys = video->phys; | ||
1941 | input->id.bustype = BUS_HOST; | ||
1942 | input->id.product = 0x06; | ||
1943 | input->evbit[0] = BIT(EV_KEY); | ||
1944 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | ||
1945 | set_bit(KEY_VIDEO_NEXT, input->keybit); | ||
1946 | set_bit(KEY_VIDEO_PREV, input->keybit); | ||
1947 | set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); | ||
1948 | set_bit(KEY_BRIGHTNESSUP, input->keybit); | ||
1949 | set_bit(KEY_BRIGHTNESSDOWN, input->keybit); | ||
1950 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | ||
1951 | set_bit(KEY_DISPLAY_OFF, input->keybit); | ||
1952 | set_bit(KEY_UNKNOWN, input->keybit); | ||
1953 | result = input_register_device(input); | ||
1954 | if (result) { | ||
1955 | acpi_remove_notify_handler(video->device->handle, | ||
1956 | ACPI_DEVICE_NOTIFY, | ||
1957 | acpi_video_bus_notify); | ||
1958 | acpi_video_bus_stop_devices(video); | ||
1959 | acpi_video_bus_put_devices(video); | ||
1960 | kfree(video->attached_array); | ||
1961 | acpi_video_bus_remove_fs(device); | ||
1962 | goto end; | ||
1963 | } | ||
1964 | |||
1965 | |||
1884 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1966 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1885 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1967 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
1886 | video->flags.multihead ? "yes" : "no", | 1968 | video->flags.multihead ? "yes" : "no", |
@@ -1914,6 +1996,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
1914 | acpi_video_bus_put_devices(video); | 1996 | acpi_video_bus_put_devices(video); |
1915 | acpi_video_bus_remove_fs(device); | 1997 | acpi_video_bus_remove_fs(device); |
1916 | 1998 | ||
1999 | input_unregister_device(video->input); | ||
1917 | kfree(video->attached_array); | 2000 | kfree(video->attached_array); |
1918 | kfree(video); | 2001 | kfree(video); |
1919 | 2002 | ||
diff --git a/include/linux/input.h b/include/linux/input.h index e02c6a66b2ba..cf2b5619aa13 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -363,6 +363,12 @@ struct input_absinfo { | |||
363 | 363 | ||
364 | #define KEY_UNKNOWN 240 | 364 | #define KEY_UNKNOWN 240 |
365 | 365 | ||
366 | #define KEY_VIDEO_NEXT 241 /* drive next video source */ | ||
367 | #define KEY_VIDEO_PREV 242 /* drive previous video source */ | ||
368 | #define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ | ||
369 | #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */ | ||
370 | #define KEY_DISPLAY_OFF 245 /* display device to off state */ | ||
371 | |||
366 | #define BTN_MISC 0x100 | 372 | #define BTN_MISC 0x100 |
367 | #define BTN_0 0x100 | 373 | #define BTN_0 0x100 |
368 | #define BTN_1 0x101 | 374 | #define BTN_1 0x101 |