Loading drivers/platform/x86/hp-wmi.c +187 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ * HP WMI hotkeys * * Copyright (C) 2008 Red Hat <mjg@redhat.com> * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi> * * Portions based on wistron_btns.c: * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> Loading Loading @@ -51,6 +52,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_HARDWARE_QUERY 0x4 #define HPWMI_WIRELESS_QUERY 0x5 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_WIRELESS2_QUERY 0x1b #define PREFIX "HP WMI: " #define UNIMP "Unimplemented " Loading Loading @@ -95,6 +97,39 @@ enum hp_return_value { HPWMI_RET_INVALID_PARAMETERS = 0x05, }; enum hp_wireless2_bits { HPWMI_POWER_STATE = 0x01, HPWMI_POWER_SOFT = 0x02, HPWMI_POWER_BIOS = 0x04, HPWMI_POWER_HARD = 0x08, }; #define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \ != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) #define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT) struct bios_rfkill2_device_state { u8 radio_type; u8 bus_type; u16 vendor_id; u16 product_id; u16 subsys_vendor_id; u16 subsys_product_id; u8 rfkill_id; u8 power; u8 unknown[4]; }; /* 7 devices fit into the 128 byte buffer */ #define HPWMI_MAX_RFKILL2_DEVICES 7 struct bios_rfkill2_state { u8 unknown[7]; u8 count; u8 pad[8]; struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES]; }; static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } }, { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } }, Loading @@ -114,6 +149,15 @@ static struct rfkill *wifi_rfkill; static struct rfkill *bluetooth_rfkill; static struct rfkill *wwan_rfkill; struct rfkill2_device { u8 id; int num; struct rfkill *rfkill; }; static int rfkill2_count; static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; static const struct dev_pm_ops hp_wmi_pm_ops = { .resume = hp_wmi_resume_handler, .restore = hp_wmi_resume_handler, Loading Loading @@ -308,6 +352,51 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) return true; } static int hp_wmi_rfkill2_set_block(void *data, bool blocked) { int rfkill_id = (int)(long)data; char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked }; if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1, buffer, sizeof(buffer), 0)) return -EINVAL; return 0; } static const struct rfkill_ops hp_wmi_rfkill2_ops = { .set_block = hp_wmi_rfkill2_set_block, }; static int hp_wmi_rfkill2_refresh(void) { int err, i; struct bios_rfkill2_state state; err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 0, sizeof(state)); if (err) return err; for (i = 0; i < rfkill2_count; i++) { int num = rfkill2[i].num; struct bios_rfkill2_device_state *devstate; devstate = &state.device[num]; if (num >= state.count || devstate->rfkill_id != rfkill2[i].id) { printk(KERN_WARNING PREFIX "power configuration of " "the wireless devices unexpectedly changed\n"); continue; } rfkill_set_states(rfkill2[i].rfkill, IS_SWBLOCKED(devstate->power), IS_HWBLOCKED(devstate->power)); } return 0; } static ssize_t show_display(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -442,6 +531,11 @@ static void hp_wmi_notify(u32 value, void *context) key_code); break; case HPWMI_WIRELESS: if (rfkill2_count) { hp_wmi_rfkill2_refresh(); break; } if (wifi_rfkill) rfkill_set_states(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI), Loading Loading @@ -601,6 +695,87 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) return err; } static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device) { int err, i; struct bios_rfkill2_state state; err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 0, sizeof(state)); if (err) return err; if (state.count > HPWMI_MAX_RFKILL2_DEVICES) { printk(KERN_WARNING PREFIX "unable to parse 0x1b query output\n"); return -EINVAL; } for (i = 0; i < state.count; i++) { struct rfkill *rfkill; enum rfkill_type type; char *name; switch (state.device[i].radio_type) { case HPWMI_WIFI: type = RFKILL_TYPE_WLAN; name = "hp-wifi"; break; case HPWMI_BLUETOOTH: type = RFKILL_TYPE_BLUETOOTH; name = "hp-bluetooth"; break; case HPWMI_WWAN: type = RFKILL_TYPE_WWAN; name = "hp-wwan"; break; default: printk(KERN_WARNING PREFIX "unknown device type 0x%x\n", state.device[i].radio_type); continue; } if (!state.device[i].vendor_id) { printk(KERN_WARNING PREFIX "zero device %d while %d " "reported\n", i, state.count); continue; } rfkill = rfkill_alloc(name, &device->dev, type, &hp_wmi_rfkill2_ops, (void *)(long)i); if (!rfkill) { err = -ENOMEM; goto fail; } rfkill2[rfkill2_count].id = state.device[i].rfkill_id; rfkill2[rfkill2_count].num = i; rfkill2[rfkill2_count].rfkill = rfkill; rfkill_init_sw_state(rfkill, IS_SWBLOCKED(state.device[i].power)); rfkill_set_hw_state(rfkill, IS_HWBLOCKED(state.device[i].power)); if (!(state.device[i].power & HPWMI_POWER_BIOS)) printk(KERN_INFO PREFIX "device %s blocked by BIOS\n", name); err = rfkill_register(rfkill); if (err) { rfkill_destroy(rfkill); goto fail; } rfkill2_count++; } return 0; fail: for (; rfkill2_count > 0; rfkill2_count--) { rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill); rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill); } return err; } static int __devinit hp_wmi_bios_setup(struct platform_device *device) { int err; Loading @@ -609,8 +784,10 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device) wifi_rfkill = NULL; bluetooth_rfkill = NULL; wwan_rfkill = NULL; rfkill2_count = 0; hp_wmi_rfkill_setup(device); if (hp_wmi_rfkill_setup(device)) hp_wmi_rfkill2_setup(device); err = device_create_file(&device->dev, &dev_attr_display); if (err) Loading @@ -636,8 +813,14 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device) static int __exit hp_wmi_bios_remove(struct platform_device *device) { int i; cleanup_sysfs(device); for (i = 0; i < rfkill2_count; i++) { rfkill_unregister(rfkill2[i].rfkill); rfkill_destroy(rfkill2[i].rfkill); } if (wifi_rfkill) { rfkill_unregister(wifi_rfkill); rfkill_destroy(wifi_rfkill); Loading Loading @@ -670,6 +853,9 @@ static int hp_wmi_resume_handler(struct device *device) input_sync(hp_wmi_input_dev); } if (rfkill2_count) hp_wmi_rfkill2_refresh(); if (wifi_rfkill) rfkill_set_states(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI), Loading Loading
drivers/platform/x86/hp-wmi.c +187 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ * HP WMI hotkeys * * Copyright (C) 2008 Red Hat <mjg@redhat.com> * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi> * * Portions based on wistron_btns.c: * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> Loading Loading @@ -51,6 +52,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_HARDWARE_QUERY 0x4 #define HPWMI_WIRELESS_QUERY 0x5 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_WIRELESS2_QUERY 0x1b #define PREFIX "HP WMI: " #define UNIMP "Unimplemented " Loading Loading @@ -95,6 +97,39 @@ enum hp_return_value { HPWMI_RET_INVALID_PARAMETERS = 0x05, }; enum hp_wireless2_bits { HPWMI_POWER_STATE = 0x01, HPWMI_POWER_SOFT = 0x02, HPWMI_POWER_BIOS = 0x04, HPWMI_POWER_HARD = 0x08, }; #define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \ != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) #define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT) struct bios_rfkill2_device_state { u8 radio_type; u8 bus_type; u16 vendor_id; u16 product_id; u16 subsys_vendor_id; u16 subsys_product_id; u8 rfkill_id; u8 power; u8 unknown[4]; }; /* 7 devices fit into the 128 byte buffer */ #define HPWMI_MAX_RFKILL2_DEVICES 7 struct bios_rfkill2_state { u8 unknown[7]; u8 count; u8 pad[8]; struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES]; }; static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } }, { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } }, Loading @@ -114,6 +149,15 @@ static struct rfkill *wifi_rfkill; static struct rfkill *bluetooth_rfkill; static struct rfkill *wwan_rfkill; struct rfkill2_device { u8 id; int num; struct rfkill *rfkill; }; static int rfkill2_count; static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; static const struct dev_pm_ops hp_wmi_pm_ops = { .resume = hp_wmi_resume_handler, .restore = hp_wmi_resume_handler, Loading Loading @@ -308,6 +352,51 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) return true; } static int hp_wmi_rfkill2_set_block(void *data, bool blocked) { int rfkill_id = (int)(long)data; char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked }; if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1, buffer, sizeof(buffer), 0)) return -EINVAL; return 0; } static const struct rfkill_ops hp_wmi_rfkill2_ops = { .set_block = hp_wmi_rfkill2_set_block, }; static int hp_wmi_rfkill2_refresh(void) { int err, i; struct bios_rfkill2_state state; err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 0, sizeof(state)); if (err) return err; for (i = 0; i < rfkill2_count; i++) { int num = rfkill2[i].num; struct bios_rfkill2_device_state *devstate; devstate = &state.device[num]; if (num >= state.count || devstate->rfkill_id != rfkill2[i].id) { printk(KERN_WARNING PREFIX "power configuration of " "the wireless devices unexpectedly changed\n"); continue; } rfkill_set_states(rfkill2[i].rfkill, IS_SWBLOCKED(devstate->power), IS_HWBLOCKED(devstate->power)); } return 0; } static ssize_t show_display(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -442,6 +531,11 @@ static void hp_wmi_notify(u32 value, void *context) key_code); break; case HPWMI_WIRELESS: if (rfkill2_count) { hp_wmi_rfkill2_refresh(); break; } if (wifi_rfkill) rfkill_set_states(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI), Loading Loading @@ -601,6 +695,87 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) return err; } static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device) { int err, i; struct bios_rfkill2_state state; err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state, 0, sizeof(state)); if (err) return err; if (state.count > HPWMI_MAX_RFKILL2_DEVICES) { printk(KERN_WARNING PREFIX "unable to parse 0x1b query output\n"); return -EINVAL; } for (i = 0; i < state.count; i++) { struct rfkill *rfkill; enum rfkill_type type; char *name; switch (state.device[i].radio_type) { case HPWMI_WIFI: type = RFKILL_TYPE_WLAN; name = "hp-wifi"; break; case HPWMI_BLUETOOTH: type = RFKILL_TYPE_BLUETOOTH; name = "hp-bluetooth"; break; case HPWMI_WWAN: type = RFKILL_TYPE_WWAN; name = "hp-wwan"; break; default: printk(KERN_WARNING PREFIX "unknown device type 0x%x\n", state.device[i].radio_type); continue; } if (!state.device[i].vendor_id) { printk(KERN_WARNING PREFIX "zero device %d while %d " "reported\n", i, state.count); continue; } rfkill = rfkill_alloc(name, &device->dev, type, &hp_wmi_rfkill2_ops, (void *)(long)i); if (!rfkill) { err = -ENOMEM; goto fail; } rfkill2[rfkill2_count].id = state.device[i].rfkill_id; rfkill2[rfkill2_count].num = i; rfkill2[rfkill2_count].rfkill = rfkill; rfkill_init_sw_state(rfkill, IS_SWBLOCKED(state.device[i].power)); rfkill_set_hw_state(rfkill, IS_HWBLOCKED(state.device[i].power)); if (!(state.device[i].power & HPWMI_POWER_BIOS)) printk(KERN_INFO PREFIX "device %s blocked by BIOS\n", name); err = rfkill_register(rfkill); if (err) { rfkill_destroy(rfkill); goto fail; } rfkill2_count++; } return 0; fail: for (; rfkill2_count > 0; rfkill2_count--) { rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill); rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill); } return err; } static int __devinit hp_wmi_bios_setup(struct platform_device *device) { int err; Loading @@ -609,8 +784,10 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device) wifi_rfkill = NULL; bluetooth_rfkill = NULL; wwan_rfkill = NULL; rfkill2_count = 0; hp_wmi_rfkill_setup(device); if (hp_wmi_rfkill_setup(device)) hp_wmi_rfkill2_setup(device); err = device_create_file(&device->dev, &dev_attr_display); if (err) Loading @@ -636,8 +813,14 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device) static int __exit hp_wmi_bios_remove(struct platform_device *device) { int i; cleanup_sysfs(device); for (i = 0; i < rfkill2_count; i++) { rfkill_unregister(rfkill2[i].rfkill); rfkill_destroy(rfkill2[i].rfkill); } if (wifi_rfkill) { rfkill_unregister(wifi_rfkill); rfkill_destroy(wifi_rfkill); Loading Loading @@ -670,6 +853,9 @@ static int hp_wmi_resume_handler(struct device *device) input_sync(hp_wmi_input_dev); } if (rfkill2_count) hp_wmi_rfkill2_refresh(); if (wifi_rfkill) rfkill_set_states(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI), Loading