summaryrefslogtreecommitdiffstats
path: root/linux-2.6-dell-laptop-rfkill-fix.patch
diff options
context:
space:
mode:
authorJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
committerJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
commit2f82dda4a9bf41e64e864889bf06564bdf826e25 (patch)
tree118a7b483ae5de4dbf83d20001302f1404866ef0 /linux-2.6-dell-laptop-rfkill-fix.patch
parent64ba2e5ffde5f2418eb26c700cb0ab62b04e5013 (diff)
downloaddom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.gz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.xz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.zip
initial srpm import
Diffstat (limited to 'linux-2.6-dell-laptop-rfkill-fix.patch')
-rw-r--r--linux-2.6-dell-laptop-rfkill-fix.patch323
1 files changed, 323 insertions, 0 deletions
diff --git a/linux-2.6-dell-laptop-rfkill-fix.patch b/linux-2.6-dell-laptop-rfkill-fix.patch
new file mode 100644
index 0000000..336788c
--- /dev/null
+++ b/linux-2.6-dell-laptop-rfkill-fix.patch
@@ -0,0 +1,323 @@
+diff --git a/drivers/input/input.c b/drivers/input/input.c
+index 7c237e6..80f1e48 100644
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -88,19 +88,26 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
+ */
+ static void input_pass_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
+-{
+- struct input_handle *handle;
++
++{ struct input_handle *handle;
+
+ rcu_read_lock();
+
+ handle = rcu_dereference(dev->grab);
+- if (handle)
++ if (handle) {
+ handle->handler->event(handle, type, code, value);
+- else
+- list_for_each_entry_rcu(handle, &dev->h_list, d_node)
+- if (handle->open)
+- handle->handler->event(handle,
+- type, code, value);
++ goto out;
++ }
++
++ handle = rcu_dereference(dev->filter);
++ if (handle && handle->handler->filter(handle, type, code, value))
++ goto out;
++
++ list_for_each_entry_rcu(handle, &dev->h_list, d_node)
++ if (handle->open)
++ handle->handler->event(handle,
++ type, code, value);
++out:
+ rcu_read_unlock();
+ }
+
+@@ -375,12 +382,15 @@ int input_grab_device(struct input_handle *handle)
+ }
+ EXPORT_SYMBOL(input_grab_device);
+
+-static void __input_release_device(struct input_handle *handle)
++static void __input_release_device(struct input_handle *handle, bool filter)
+ {
+ struct input_dev *dev = handle->dev;
+
+- if (dev->grab == handle) {
+- rcu_assign_pointer(dev->grab, NULL);
++ if (handle == (filter ? dev->filter : dev->grab)) {
++ if (filter)
++ rcu_assign_pointer(dev->filter, NULL);
++ else
++ rcu_assign_pointer(dev->grab, NULL);
+ /* Make sure input_pass_event() notices that grab is gone */
+ synchronize_rcu();
+
+@@ -404,12 +414,65 @@ void input_release_device(struct input_handle *handle)
+ struct input_dev *dev = handle->dev;
+
+ mutex_lock(&dev->mutex);
+- __input_release_device(handle);
++ __input_release_device(handle, false);
+ mutex_unlock(&dev->mutex);
+ }
+ EXPORT_SYMBOL(input_release_device);
+
+ /**
++ * input_filter_device - allow input events to be filtered from higher layers
++ * @handle: input handle that wants to filter the device
++ *
++ * When a device is filtered by an input handle all events generated by
++ * the device are to this handle. If the filter function returns true then
++ * the event is discarded rather than being passed to any other input handles,
++ * otherwise it is passed to them as normal. Grabs will be handled before
++ * filters, so a grabbed device will not deliver events to a filter function.
++ */
++int input_filter_device(struct input_handle *handle)
++{
++ struct input_dev *dev = handle->dev;
++ int retval;
++
++ retval = mutex_lock_interruptible(&dev->mutex);
++ if (retval)
++ return retval;
++
++ if (dev->filter) {
++ retval = -EBUSY;
++ goto out;
++ }
++
++ rcu_assign_pointer(dev->filter, handle);
++ synchronize_rcu();
++
++ out:
++ mutex_unlock(&dev->mutex);
++ return retval;
++}
++EXPORT_SYMBOL(input_filter_device);
++
++/**
++ * input_unfilter_device - removes a filter from a device
++ * @handle: input handle that owns the device
++ *
++ * Removes the filter from a device so that other input handles can
++ * start receiving unfiltered input events. Upon release all handlers
++ * attached to the device have their start() method called so they
++ * have a change to synchronize device state with the rest of the
++ * system.
++ */
++void input_unfilter_device(struct input_handle *handle)
++{
++ struct input_dev *dev = handle->dev;
++
++ mutex_lock(&dev->mutex);
++ __input_release_device(handle, true);
++ mutex_unlock(&dev->mutex);
++}
++EXPORT_SYMBOL(input_unfilter_device);
++
++/**
+ * input_open_device - open input device
+ * @handle: handle through which device is being accessed
+ *
+@@ -482,7 +545,9 @@ void input_close_device(struct input_handle *handle)
+
+ mutex_lock(&dev->mutex);
+
+- __input_release_device(handle);
++ /* Release both grabs and filters */
++ __input_release_device(handle, false);
++ __input_release_device(handle, true);
+
+ if (!--dev->users && dev->close)
+ dev->close(dev);
+diff --git a/include/linux/input.h b/include/linux/input.h
+index 8b3bc3e..e28f116 100644
+--- a/include/linux/input.h
++++ b/include/linux/input.h
+@@ -1118,6 +1118,7 @@ struct input_dev {
+ int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+
+ struct input_handle *grab;
++ struct input_handle *filter;
+
+ spinlock_t event_lock;
+ struct mutex mutex;
+@@ -1218,6 +1219,7 @@ struct input_handler {
+ void *private;
+
+ void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
++ bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
+ int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
+ void (*disconnect)(struct input_handle *handle);
+ void (*start)(struct input_handle *handle);
+@@ -1295,6 +1297,9 @@ void input_unregister_handle(struct input_handle *);
+ int input_grab_device(struct input_handle *);
+ void input_release_device(struct input_handle *);
+
++int input_filter_device(struct input_handle *);
++void input_unfilter_device(struct input_handle *);
++
+ int input_open_device(struct input_handle *);
+ void input_close_device(struct input_handle *);
+
+diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
+index 74909c4..71a4149 100644
+--- a/drivers/platform/x86/dell-laptop.c
++++ b/drivers/platform/x86/dell-laptop.c
+@@ -22,6 +22,7 @@
+ #include <linux/rfkill.h>
+ #include <linux/power_supply.h>
+ #include <linux/acpi.h>
++#include <linux/input.h>
+ #include "../../firmware/dcdbas.h"
+
+ #define BRIGHTNESS_TOKEN 0x7d
+@@ -206,6 +207,16 @@ static const struct rfkill_ops dell_rfkill_ops = {
+ .query = dell_rfkill_query,
+ };
+
++static void dell_rfkill_update(void)
++{
++ if (wifi_rfkill)
++ dell_rfkill_query(wifi_rfkill, (void *)1);
++ if (bluetooth_rfkill)
++ dell_rfkill_query(bluetooth_rfkill, (void *)2);
++ if (wwan_rfkill)
++ dell_rfkill_query(wwan_rfkill, (void *)3);
++}
++
+ static int dell_setup_rfkill(void)
+ {
+ struct calling_interface_buffer buffer;
+@@ -310,6 +321,90 @@ static struct backlight_ops dell_ops = {
+ .update_status = dell_send_intensity,
+ };
+
++static const struct input_device_id dell_input_ids[] = {
++ {
++ .bustype = 0x11,
++ .vendor = 0x01,
++ .product = 0x01,
++ .version = 0xab41,
++ .flags = INPUT_DEVICE_ID_MATCH_BUS |
++ INPUT_DEVICE_ID_MATCH_VENDOR |
++ INPUT_DEVICE_ID_MATCH_PRODUCT |
++ INPUT_DEVICE_ID_MATCH_VERSION
++ },
++ { },
++};
++
++static bool dell_input_filter(struct input_handle *handle, unsigned int type,
++ unsigned int code, int value)
++{
++ if (type == EV_KEY && code == KEY_WLAN && value == 1) {
++ dell_rfkill_update();
++ return 1;
++ }
++
++ return 0;
++}
++
++static void dell_input_event(struct input_handle *handle, unsigned int type,
++ unsigned int code, int value)
++{
++}
++
++static int dell_input_connect(struct input_handler *handler,
++ struct input_dev *dev,
++ const struct input_device_id *id)
++{
++ struct input_handle *handle;
++ int error;
++
++ handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
++ if (!handle)
++ return -ENOMEM;
++
++ handle->dev = dev;
++ handle->handler = handler;
++ handle->name = "dell-laptop";
++
++ error = input_register_handle(handle);
++ if (error)
++ goto err_free_handle;
++
++ error = input_open_device(handle);
++ if (error)
++ goto err_unregister_handle;
++
++ error = input_filter_device(handle);
++ if (error)
++ goto err_close_handle;
++
++ return 0;
++
++err_close_handle:
++ input_close_device(handle);
++err_unregister_handle:
++ input_unregister_handle(handle);
++err_free_handle:
++ kfree(handle);
++ return error;
++}
++
++static void dell_input_disconnect(struct input_handle *handle)
++{
++ input_close_device(handle);
++ input_unregister_handle(handle);
++ kfree(handle);
++}
++
++static struct input_handler dell_input_handler = {
++ .name = "dell-laptop",
++ .filter = dell_input_filter,
++ .event = dell_input_event,
++ .connect = dell_input_connect,
++ .disconnect = dell_input_disconnect,
++ .id_table = dell_input_ids,
++};
++
+ static int __init dell_init(void)
+ {
+ struct calling_interface_buffer buffer;
+@@ -333,6 +428,10 @@ static int __init dell_init(void)
+ goto out;
+ }
+
++ if (input_register_handler(&dell_input_handler))
++ printk(KERN_INFO
++ "dell-laptop: Could not register input filter\n");
++
+ #ifdef CONFIG_ACPI
+ /* In the event of an ACPI backlight being available, don't
+ * register the platform controller.
+@@ -388,6 +487,7 @@ static void __exit dell_exit(void)
+ rfkill_unregister(bluetooth_rfkill);
+ if (wwan_rfkill)
+ rfkill_unregister(wwan_rfkill);
++ input_unregister_handler(&dell_input_handler);
+ }
+
+ module_init(dell_init);
+diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
+index 71a4149..e559fa1 100644
+--- a/drivers/platform/x86/dell-laptop.c
++++ b/drivers/platform/x86/dell-laptop.c
+@@ -198,8 +198,8 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data)
+ dell_send_request(&buffer, 17, 11);
+ status = buffer.output[1];
+
+- if (status & BIT(bit))
+- rfkill_set_hw_state(rfkill, !!(status & BIT(16)));
++ rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
++ rfkill_set_hw_state(rfkill, !(status & BIT(16)));
+ }
+
+ static const struct rfkill_ops dell_rfkill_ops = {
+--
+1.6.3.3
+