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>
This commit is contained in:
parent
3bb970214f
commit
339e75329a
1 changed files with 58 additions and 1 deletions
|
@ -59,6 +59,7 @@
|
||||||
#include <linux/backlight.h>
|
#include <linux/backlight.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/rfkill.h>
|
#include <linux/rfkill.h>
|
||||||
|
#include <linux/i8042.h>
|
||||||
|
|
||||||
#define MSI_DRIVER_VERSION "0.5"
|
#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)
|
static void msi_init_rfkill(struct work_struct *ignored)
|
||||||
{
|
{
|
||||||
if (rfk_wlan) {
|
if (rfk_wlan) {
|
||||||
|
@ -706,9 +747,24 @@ static int load_scm_model_init(struct platform_device *sdev)
|
||||||
/* initial rfkill */
|
/* initial rfkill */
|
||||||
result = rfkill_init(sdev);
|
result = rfkill_init(sdev);
|
||||||
if (result < 0)
|
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;
|
return 0;
|
||||||
|
|
||||||
|
fail_filter:
|
||||||
|
rfkill_cleanup();
|
||||||
|
|
||||||
|
fail_rfkill:
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init msi_init(void)
|
static int __init msi_init(void)
|
||||||
|
@ -819,6 +875,7 @@ static void __exit msi_cleanup(void)
|
||||||
platform_driver_unregister(&msipf_driver);
|
platform_driver_unregister(&msipf_driver);
|
||||||
backlight_device_unregister(msibl_device);
|
backlight_device_unregister(msibl_device);
|
||||||
|
|
||||||
|
i8042_remove_filter(msi_laptop_i8042_filter);
|
||||||
rfkill_cleanup();
|
rfkill_cleanup();
|
||||||
|
|
||||||
/* Enable automatic brightness control again */
|
/* Enable automatic brightness control again */
|
||||||
|
|
Reference in a new issue