diff options
author | Lee, Chun-Yi <jlee@novell.com> | 2010-05-12 09:58:10 -0700 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-05-20 09:45:56 -0400 |
commit | 339e75329a447363658d08833bf9f98909f419cd (patch) | |
tree | 3552e57ca6298c538a935019365dd44c94c3286f /drivers/platform | |
parent | 3bb970214fce6495573843e4b7b786f8ea94cd70 (diff) |
msi-laptop: Add i8042 filter to sync sw state with BIOS when function key pressed
There have some MSI netbook change devices state by EC when user press
wlan/bluetooth/wwan function keys. So, add a i8042 filter to sync sw
state with BIOS when function keys pressed.
Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/msi-laptop.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 34bec2e26843..b08a108c9776 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -59,6 +59,7 @@ #include <linux/backlight.h> #include <linux/platform_device.h> #include <linux/rfkill.h> +#include <linux/i8042.h> #define MSI_DRIVER_VERSION "0.5" @@ -581,6 +582,46 @@ static void rfkill_cleanup(void) } } +static void msi_update_rfkill(struct work_struct *ignored) +{ + get_wireless_state_ec_standard(); + + if (rfk_wlan) + rfkill_set_sw_state(rfk_wlan, !wlan_s); + if (rfk_bluetooth) + rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s); + if (rfk_threeg) + rfkill_set_sw_state(rfk_threeg, !threeg_s); +} +static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill); + +static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & 0x20) + return false; + + /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan*/ + if (unlikely(data == 0xe0)) { + extended = true; + return false; + } else if (unlikely(extended)) { + switch (data) { + case 0x54: + case 0x62: + case 0x76: + schedule_delayed_work(&msi_rfkill_work, + round_jiffies_relative(0.5 * HZ)); + break; + } + extended = false; + } + + return false; +} + static void msi_init_rfkill(struct work_struct *ignored) { if (rfk_wlan) { @@ -706,9 +747,24 @@ static int load_scm_model_init(struct platform_device *sdev) /* initial rfkill */ result = rfkill_init(sdev); if (result < 0) - return result; + goto fail_rfkill; + + result = i8042_install_filter(msi_laptop_i8042_filter); + if (result) { + printk(KERN_ERR + "msi-laptop: Unable to install key filter\n"); + goto fail_filter; + } return 0; + +fail_filter: + rfkill_cleanup(); + +fail_rfkill: + + return result; + } static int __init msi_init(void) @@ -819,6 +875,7 @@ static void __exit msi_cleanup(void) platform_driver_unregister(&msipf_driver); backlight_device_unregister(msibl_device); + i8042_remove_filter(msi_laptop_i8042_filter); rfkill_cleanup(); /* Enable automatic brightness control again */ |