aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/hp-wmi.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/platform/x86/hp-wmi.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/platform/x86/hp-wmi.c')
-rw-r--r--drivers/platform/x86/hp-wmi.c180
1 files changed, 111 insertions, 69 deletions
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index c2842171cec6..51c07a05a7bc 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -26,6 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/slab.h>
29#include <linux/types.h> 30#include <linux/types.h>
30#include <linux/input.h> 31#include <linux/input.h>
31#include <acpi/acpi_drivers.h> 32#include <acpi/acpi_drivers.h>
@@ -51,7 +52,13 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
51#define HPWMI_WIRELESS_QUERY 0x5 52#define HPWMI_WIRELESS_QUERY 0x5
52#define HPWMI_HOTKEY_QUERY 0xc 53#define HPWMI_HOTKEY_QUERY 0xc
53 54
54static int __init hp_wmi_bios_setup(struct platform_device *device); 55enum hp_wmi_radio {
56 HPWMI_WIFI = 0,
57 HPWMI_BLUETOOTH = 1,
58 HPWMI_WWAN = 2,
59};
60
61static int __devinit hp_wmi_bios_setup(struct platform_device *device);
55static int __exit hp_wmi_bios_remove(struct platform_device *device); 62static int __exit hp_wmi_bios_remove(struct platform_device *device);
56static int hp_wmi_resume_handler(struct device *device); 63static int hp_wmi_resume_handler(struct device *device);
57 64
@@ -83,6 +90,7 @@ static struct key_entry hp_wmi_keymap[] = {
83 {KE_KEY, 0x20e6, KEY_PROG1}, 90 {KE_KEY, 0x20e6, KEY_PROG1},
84 {KE_KEY, 0x2142, KEY_MEDIA}, 91 {KE_KEY, 0x2142, KEY_MEDIA},
85 {KE_KEY, 0x213b, KEY_INFO}, 92 {KE_KEY, 0x213b, KEY_INFO},
93 {KE_KEY, 0x2169, KEY_DIRECTION},
86 {KE_KEY, 0x231b, KEY_HELP}, 94 {KE_KEY, 0x231b, KEY_HELP},
87 {KE_END, 0} 95 {KE_END, 0}
88}; 96};
@@ -94,7 +102,7 @@ static struct rfkill *wifi_rfkill;
94static struct rfkill *bluetooth_rfkill; 102static struct rfkill *bluetooth_rfkill;
95static struct rfkill *wwan_rfkill; 103static struct rfkill *wwan_rfkill;
96 104
97static struct dev_pm_ops hp_wmi_pm_ops = { 105static const struct dev_pm_ops hp_wmi_pm_ops = {
98 .resume = hp_wmi_resume_handler, 106 .resume = hp_wmi_resume_handler,
99 .restore = hp_wmi_resume_handler, 107 .restore = hp_wmi_resume_handler,
100}; 108};
@@ -128,10 +136,15 @@ static int hp_wmi_perform_query(int query, int write, int value)
128 136
129 obj = output.pointer; 137 obj = output.pointer;
130 138
131 if (!obj || obj->type != ACPI_TYPE_BUFFER) 139 if (!obj)
140 return -EINVAL;
141 else if (obj->type != ACPI_TYPE_BUFFER) {
142 kfree(obj);
132 return -EINVAL; 143 return -EINVAL;
144 }
133 145
134 bios_return = *((struct bios_return *)obj->buffer.pointer); 146 bios_return = *((struct bios_return *)obj->buffer.pointer);
147 kfree(obj);
135 if (bios_return.return_code > 0) 148 if (bios_return.return_code > 0)
136 return bios_return.return_code * -1; 149 return bios_return.return_code * -1;
137 else 150 else
@@ -175,8 +188,8 @@ static int hp_wmi_tablet_state(void)
175 188
176static int hp_wmi_set_block(void *data, bool blocked) 189static int hp_wmi_set_block(void *data, bool blocked)
177{ 190{
178 unsigned long b = (unsigned long) data; 191 enum hp_wmi_radio r = (enum hp_wmi_radio) data;
179 int query = BIT(b + 8) | ((!blocked) << b); 192 int query = BIT(r + 8) | ((!blocked) << r);
180 193
181 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); 194 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
182} 195}
@@ -185,31 +198,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
185 .set_block = hp_wmi_set_block, 198 .set_block = hp_wmi_set_block,
186}; 199};
187 200
188static bool hp_wmi_wifi_state(void) 201static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
189{ 202{
190 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 203 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
204 int mask = 0x200 << (r * 8);
191 205
192 if (wireless & 0x100) 206 if (wireless & mask)
193 return false; 207 return false;
194 else 208 else
195 return true; 209 return true;
196} 210}
197 211
198static bool hp_wmi_bluetooth_state(void) 212static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
199{ 213{
200 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 214 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
215 int mask = 0x800 << (r * 8);
201 216
202 if (wireless & 0x10000) 217 if (wireless & mask)
203 return false;
204 else
205 return true;
206}
207
208static bool hp_wmi_wwan_state(void)
209{
210 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
211
212 if (wireless & 0x1000000)
213 return false; 218 return false;
214 else 219 else
215 return true; 220 return true;
@@ -274,7 +279,7 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
274static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 279static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
275static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); 280static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
276 281
277static struct key_entry *hp_wmi_get_entry_by_scancode(int code) 282static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
278{ 283{
279 struct key_entry *key; 284 struct key_entry *key;
280 285
@@ -285,7 +290,7 @@ static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
285 return NULL; 290 return NULL;
286} 291}
287 292
288static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) 293static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
289{ 294{
290 struct key_entry *key; 295 struct key_entry *key;
291 296
@@ -296,7 +301,8 @@ static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode)
296 return NULL; 301 return NULL;
297} 302}
298 303
299static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) 304static int hp_wmi_getkeycode(struct input_dev *dev,
305 unsigned int scancode, unsigned int *keycode)
300{ 306{
301 struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode); 307 struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
302 308
@@ -308,13 +314,11 @@ static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode)
308 return -EINVAL; 314 return -EINVAL;
309} 315}
310 316
311static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) 317static int hp_wmi_setkeycode(struct input_dev *dev,
318 unsigned int scancode, unsigned int keycode)
312{ 319{
313 struct key_entry *key; 320 struct key_entry *key;
314 int old_keycode; 321 unsigned int old_keycode;
315
316 if (keycode < 0 || keycode > KEY_MAX)
317 return -EINVAL;
318 322
319 key = hp_wmi_get_entry_by_scancode(scancode); 323 key = hp_wmi_get_entry_by_scancode(scancode);
320 if (key && key->type == KE_KEY) { 324 if (key && key->type == KE_KEY) {
@@ -334,49 +338,62 @@ static void hp_wmi_notify(u32 value, void *context)
334 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 338 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
335 static struct key_entry *key; 339 static struct key_entry *key;
336 union acpi_object *obj; 340 union acpi_object *obj;
341 int eventcode;
342 acpi_status status;
337 343
338 wmi_get_event_data(value, &response); 344 status = wmi_get_event_data(value, &response);
345 if (status != AE_OK) {
346 printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status);
347 return;
348 }
339 349
340 obj = (union acpi_object *)response.pointer; 350 obj = (union acpi_object *)response.pointer;
341 351
342 if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) { 352 if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
343 int eventcode = *((u8 *) obj->buffer.pointer); 353 printk(KERN_INFO "HP WMI: Unknown response received\n");
344 if (eventcode == 0x4) 354 kfree(obj);
345 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 355 return;
346 0); 356 }
347 key = hp_wmi_get_entry_by_scancode(eventcode); 357
348 if (key) { 358 eventcode = *((u8 *) obj->buffer.pointer);
349 switch (key->type) { 359 kfree(obj);
350 case KE_KEY: 360 if (eventcode == 0x4)
351 input_report_key(hp_wmi_input_dev, 361 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
352 key->keycode, 1); 362 0);
353 input_sync(hp_wmi_input_dev); 363 key = hp_wmi_get_entry_by_scancode(eventcode);
354 input_report_key(hp_wmi_input_dev, 364 if (key) {
355 key->keycode, 0); 365 switch (key->type) {
356 input_sync(hp_wmi_input_dev); 366 case KE_KEY:
357 break; 367 input_report_key(hp_wmi_input_dev,
358 } 368 key->keycode, 1);
359 } else if (eventcode == 0x1) {
360 input_report_switch(hp_wmi_input_dev, SW_DOCK,
361 hp_wmi_dock_state());
362 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
363 hp_wmi_tablet_state());
364 input_sync(hp_wmi_input_dev); 369 input_sync(hp_wmi_input_dev);
365 } else if (eventcode == 0x5) { 370 input_report_key(hp_wmi_input_dev,
366 if (wifi_rfkill) 371 key->keycode, 0);
367 rfkill_set_sw_state(wifi_rfkill, 372 input_sync(hp_wmi_input_dev);
368 hp_wmi_wifi_state()); 373 break;
369 if (bluetooth_rfkill) 374 }
370 rfkill_set_sw_state(bluetooth_rfkill, 375 } else if (eventcode == 0x1) {
371 hp_wmi_bluetooth_state()); 376 input_report_switch(hp_wmi_input_dev, SW_DOCK,
372 if (wwan_rfkill) 377 hp_wmi_dock_state());
373 rfkill_set_sw_state(wwan_rfkill, 378 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
374 hp_wmi_wwan_state()); 379 hp_wmi_tablet_state());
375 } else 380 input_sync(hp_wmi_input_dev);
376 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", 381 } else if (eventcode == 0x5) {
377 eventcode); 382 if (wifi_rfkill)
383 rfkill_set_states(wifi_rfkill,
384 hp_wmi_get_sw_state(HPWMI_WIFI),
385 hp_wmi_get_hw_state(HPWMI_WIFI));
386 if (bluetooth_rfkill)
387 rfkill_set_states(bluetooth_rfkill,
388 hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
389 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
390 if (wwan_rfkill)
391 rfkill_set_states(wwan_rfkill,
392 hp_wmi_get_sw_state(HPWMI_WWAN),
393 hp_wmi_get_hw_state(HPWMI_WWAN));
378 } else 394 } else
379 printk(KERN_INFO "HP WMI: Unknown response received\n"); 395 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
396 eventcode);
380} 397}
381 398
382static int __init hp_wmi_input_setup(void) 399static int __init hp_wmi_input_setup(void)
@@ -430,7 +447,7 @@ static void cleanup_sysfs(struct platform_device *device)
430 device_remove_file(&device->dev, &dev_attr_tablet); 447 device_remove_file(&device->dev, &dev_attr_tablet);
431} 448}
432 449
433static int __init hp_wmi_bios_setup(struct platform_device *device) 450static int __devinit hp_wmi_bios_setup(struct platform_device *device)
434{ 451{
435 int err; 452 int err;
436 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 453 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
@@ -455,7 +472,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
455 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 472 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
456 RFKILL_TYPE_WLAN, 473 RFKILL_TYPE_WLAN,
457 &hp_wmi_rfkill_ops, 474 &hp_wmi_rfkill_ops,
458 (void *) 0); 475 (void *) HPWMI_WIFI);
476 rfkill_init_sw_state(wifi_rfkill,
477 hp_wmi_get_sw_state(HPWMI_WIFI));
478 rfkill_set_hw_state(wifi_rfkill,
479 hp_wmi_get_hw_state(HPWMI_WIFI));
459 err = rfkill_register(wifi_rfkill); 480 err = rfkill_register(wifi_rfkill);
460 if (err) 481 if (err)
461 goto register_wifi_error; 482 goto register_wifi_error;
@@ -465,7 +486,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
465 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, 486 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
466 RFKILL_TYPE_BLUETOOTH, 487 RFKILL_TYPE_BLUETOOTH,
467 &hp_wmi_rfkill_ops, 488 &hp_wmi_rfkill_ops,
468 (void *) 1); 489 (void *) HPWMI_BLUETOOTH);
490 rfkill_init_sw_state(bluetooth_rfkill,
491 hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
492 rfkill_set_hw_state(bluetooth_rfkill,
493 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
469 err = rfkill_register(bluetooth_rfkill); 494 err = rfkill_register(bluetooth_rfkill);
470 if (err) 495 if (err)
471 goto register_bluetooth_error; 496 goto register_bluetooth_error;
@@ -475,7 +500,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
475 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, 500 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
476 RFKILL_TYPE_WWAN, 501 RFKILL_TYPE_WWAN,
477 &hp_wmi_rfkill_ops, 502 &hp_wmi_rfkill_ops,
478 (void *) 2); 503 (void *) HPWMI_WWAN);
504 rfkill_init_sw_state(wwan_rfkill,
505 hp_wmi_get_sw_state(HPWMI_WWAN));
506 rfkill_set_hw_state(wwan_rfkill,
507 hp_wmi_get_hw_state(HPWMI_WWAN));
479 err = rfkill_register(wwan_rfkill); 508 err = rfkill_register(wwan_rfkill);
480 if (err) 509 if (err)
481 goto register_wwan_err; 510 goto register_wwan_err;
@@ -533,6 +562,19 @@ static int hp_wmi_resume_handler(struct device *device)
533 input_sync(hp_wmi_input_dev); 562 input_sync(hp_wmi_input_dev);
534 } 563 }
535 564
565 if (wifi_rfkill)
566 rfkill_set_states(wifi_rfkill,
567 hp_wmi_get_sw_state(HPWMI_WIFI),
568 hp_wmi_get_hw_state(HPWMI_WIFI));
569 if (bluetooth_rfkill)
570 rfkill_set_states(bluetooth_rfkill,
571 hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
572 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
573 if (wwan_rfkill)
574 rfkill_set_states(wwan_rfkill,
575 hp_wmi_get_sw_state(HPWMI_WWAN),
576 hp_wmi_get_hw_state(HPWMI_WWAN));
577
536 return 0; 578 return 0;
537} 579}
538 580
@@ -543,7 +585,7 @@ static int __init hp_wmi_init(void)
543 if (wmi_has_guid(HPWMI_EVENT_GUID)) { 585 if (wmi_has_guid(HPWMI_EVENT_GUID)) {
544 err = wmi_install_notify_handler(HPWMI_EVENT_GUID, 586 err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
545 hp_wmi_notify, NULL); 587 hp_wmi_notify, NULL);
546 if (!err) 588 if (ACPI_SUCCESS(err))
547 hp_wmi_input_setup(); 589 hp_wmi_input_setup();
548 } 590 }
549 591