Commit e5fbba85 authored by Alan Jenkins's avatar Alan Jenkins Committed by Len Brown

hp-wmi: improve rfkill support

1) Add support for reading the hardware blocked state.  Previously
   we read a combination of the hardware and software blocked states,
   reporting it as the software blocked state.  This caused some
   confusing behaviour.

2) The software state is persistent, mark it as such.

3) Check rfkill in the resume handler.  Both the hard and soft
   blocked states may change over hibernation.
Signed-off-by: default avatarAlan Jenkins <alan-jenkins@tuffmail.co.uk>
Acked-by: default avatarMatthew Garrett <mjg@redhat.com>
Tested-by: default avatarMaciej Rutecki <maciej.rutecki@gmail.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 22763c5c
...@@ -51,6 +51,12 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); ...@@ -51,6 +51,12 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
#define HPWMI_WIRELESS_QUERY 0x5 #define HPWMI_WIRELESS_QUERY 0x5
#define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_HOTKEY_QUERY 0xc
enum hp_wmi_radio {
HPWMI_WIFI = 0,
HPWMI_BLUETOOTH = 1,
HPWMI_WWAN = 2,
};
static int __init hp_wmi_bios_setup(struct platform_device *device); static int __init hp_wmi_bios_setup(struct platform_device *device);
static int __exit hp_wmi_bios_remove(struct platform_device *device); static int __exit hp_wmi_bios_remove(struct platform_device *device);
static int hp_wmi_resume_handler(struct device *device); static int hp_wmi_resume_handler(struct device *device);
...@@ -175,8 +181,8 @@ static int hp_wmi_tablet_state(void) ...@@ -175,8 +181,8 @@ static int hp_wmi_tablet_state(void)
static int hp_wmi_set_block(void *data, bool blocked) static int hp_wmi_set_block(void *data, bool blocked)
{ {
unsigned long b = (unsigned long) data; enum hp_wmi_radio r = (enum hp_wmi_radio) data;
int query = BIT(b + 8) | ((!blocked) << b); int query = BIT(r + 8) | ((!blocked) << r);
return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
} }
...@@ -185,31 +191,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = { ...@@ -185,31 +191,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
.set_block = hp_wmi_set_block, .set_block = hp_wmi_set_block,
}; };
static bool hp_wmi_wifi_state(void) static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
{
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
if (wireless & 0x100)
return false;
else
return true;
}
static bool hp_wmi_bluetooth_state(void)
{ {
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
int mask = 0x200 << (r * 8);
if (wireless & 0x10000) if (wireless & mask)
return false; return false;
else else
return true; return true;
} }
static bool hp_wmi_wwan_state(void) static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
{ {
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
int mask = 0x800 << (r * 8);
if (wireless & 0x1000000) if (wireless & mask)
return false; return false;
else else
return true; return true;
...@@ -334,49 +332,55 @@ static void hp_wmi_notify(u32 value, void *context) ...@@ -334,49 +332,55 @@ static void hp_wmi_notify(u32 value, void *context)
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
static struct key_entry *key; static struct key_entry *key;
union acpi_object *obj; union acpi_object *obj;
int eventcode;
wmi_get_event_data(value, &response); wmi_get_event_data(value, &response);
obj = (union acpi_object *)response.pointer; obj = (union acpi_object *)response.pointer;
if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) { if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
int eventcode = *((u8 *) obj->buffer.pointer); printk(KERN_INFO "HP WMI: Unknown response received\n");
if (eventcode == 0x4) return;
eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, }
0);
key = hp_wmi_get_entry_by_scancode(eventcode); eventcode = *((u8 *) obj->buffer.pointer);
if (key) { if (eventcode == 0x4)
switch (key->type) { eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
case KE_KEY: 0);
input_report_key(hp_wmi_input_dev, key = hp_wmi_get_entry_by_scancode(eventcode);
key->keycode, 1); if (key) {
input_sync(hp_wmi_input_dev); switch (key->type) {
input_report_key(hp_wmi_input_dev, case KE_KEY:
key->keycode, 0); input_report_key(hp_wmi_input_dev,
input_sync(hp_wmi_input_dev); key->keycode, 1);
break; input_sync(hp_wmi_input_dev);
} input_report_key(hp_wmi_input_dev,
} else if (eventcode == 0x1) { key->keycode, 0);
input_report_switch(hp_wmi_input_dev, SW_DOCK,
hp_wmi_dock_state());
input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
hp_wmi_tablet_state());
input_sync(hp_wmi_input_dev); input_sync(hp_wmi_input_dev);
} else if (eventcode == 0x5) { break;
if (wifi_rfkill) }
rfkill_set_sw_state(wifi_rfkill, } else if (eventcode == 0x1) {
hp_wmi_wifi_state()); input_report_switch(hp_wmi_input_dev, SW_DOCK,
if (bluetooth_rfkill) hp_wmi_dock_state());
rfkill_set_sw_state(bluetooth_rfkill, input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
hp_wmi_bluetooth_state()); hp_wmi_tablet_state());
if (wwan_rfkill) input_sync(hp_wmi_input_dev);
rfkill_set_sw_state(wwan_rfkill, } else if (eventcode == 0x5) {
hp_wmi_wwan_state()); if (wifi_rfkill)
} else rfkill_set_states(wifi_rfkill,
printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", hp_wmi_get_sw_state(HPWMI_WIFI),
eventcode); hp_wmi_get_hw_state(HPWMI_WIFI));
if (bluetooth_rfkill)
rfkill_set_states(bluetooth_rfkill,
hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
if (wwan_rfkill)
rfkill_set_states(wwan_rfkill,
hp_wmi_get_sw_state(HPWMI_WWAN),
hp_wmi_get_hw_state(HPWMI_WWAN));
} else } else
printk(KERN_INFO "HP WMI: Unknown response received\n"); printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
eventcode);
} }
static int __init hp_wmi_input_setup(void) static int __init hp_wmi_input_setup(void)
...@@ -455,7 +459,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) ...@@ -455,7 +459,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
RFKILL_TYPE_WLAN, RFKILL_TYPE_WLAN,
&hp_wmi_rfkill_ops, &hp_wmi_rfkill_ops,
(void *) 0); (void *) HPWMI_WIFI);
rfkill_init_sw_state(wifi_rfkill,
hp_wmi_get_sw_state(HPWMI_WIFI));
rfkill_set_hw_state(wifi_rfkill,
hp_wmi_get_hw_state(HPWMI_WIFI));
err = rfkill_register(wifi_rfkill); err = rfkill_register(wifi_rfkill);
if (err) if (err)
goto register_wifi_error; goto register_wifi_error;
...@@ -465,7 +473,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) ...@@ -465,7 +473,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_BLUETOOTH,
&hp_wmi_rfkill_ops, &hp_wmi_rfkill_ops,
(void *) 1); (void *) HPWMI_BLUETOOTH);
rfkill_init_sw_state(bluetooth_rfkill,
hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
rfkill_set_hw_state(bluetooth_rfkill,
hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
err = rfkill_register(bluetooth_rfkill); err = rfkill_register(bluetooth_rfkill);
if (err) if (err)
goto register_bluetooth_error; goto register_bluetooth_error;
...@@ -475,7 +487,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) ...@@ -475,7 +487,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
RFKILL_TYPE_WWAN, RFKILL_TYPE_WWAN,
&hp_wmi_rfkill_ops, &hp_wmi_rfkill_ops,
(void *) 2); (void *) HPWMI_WWAN);
rfkill_init_sw_state(wwan_rfkill,
hp_wmi_get_sw_state(HPWMI_WWAN));
rfkill_set_hw_state(wwan_rfkill,
hp_wmi_get_hw_state(HPWMI_WWAN));
err = rfkill_register(wwan_rfkill); err = rfkill_register(wwan_rfkill);
if (err) if (err)
goto register_wwan_err; goto register_wwan_err;
...@@ -533,6 +549,19 @@ static int hp_wmi_resume_handler(struct device *device) ...@@ -533,6 +549,19 @@ static int hp_wmi_resume_handler(struct device *device)
input_sync(hp_wmi_input_dev); input_sync(hp_wmi_input_dev);
} }
if (wifi_rfkill)
rfkill_set_states(wifi_rfkill,
hp_wmi_get_sw_state(HPWMI_WIFI),
hp_wmi_get_hw_state(HPWMI_WIFI));
if (bluetooth_rfkill)
rfkill_set_states(bluetooth_rfkill,
hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
if (wwan_rfkill)
rfkill_set_states(wwan_rfkill,
hp_wmi_get_sw_state(HPWMI_WWAN),
hp_wmi_get_hw_state(HPWMI_WWAN));
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment