Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hp-wmi.c
Go to the documentation of this file.
1 /*
2  * HP WMI hotkeys
3  *
4  * Copyright (C) 2008 Red Hat <[email protected]>
5  * Copyright (C) 2010, 2011 Anssi Hannula <[email protected]>
6  *
7  * Portions based on wistron_btns.c:
8  * Copyright (C) 2005 Miloslav Trmac <[email protected]>
9  * Copyright (C) 2005 Bernhard Rosenkraenzer <[email protected]>
10  * Copyright (C) 2005 Dmitry Torokhov <[email protected]>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  */
26 
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28 
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <linux/slab.h>
33 #include <linux/types.h>
34 #include <linux/input.h>
36 #include <linux/platform_device.h>
37 #include <linux/acpi.h>
38 #include <linux/rfkill.h>
39 #include <linux/string.h>
40 
41 MODULE_AUTHOR("Matthew Garrett <[email protected]>");
42 MODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
43 MODULE_LICENSE("GPL");
44 
45 MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
46 MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
47 
48 #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
49 #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
50 
51 #define HPWMI_DISPLAY_QUERY 0x1
52 #define HPWMI_HDDTEMP_QUERY 0x2
53 #define HPWMI_ALS_QUERY 0x3
54 #define HPWMI_HARDWARE_QUERY 0x4
55 #define HPWMI_WIRELESS_QUERY 0x5
56 #define HPWMI_HOTKEY_QUERY 0xc
57 #define HPWMI_WIRELESS2_QUERY 0x1b
58 
63 };
64 
73 };
74 
75 static int __devinit hp_wmi_bios_setup(struct platform_device *device);
76 static int __exit hp_wmi_bios_remove(struct platform_device *device);
77 static int hp_wmi_resume_handler(struct device *device);
78 
79 struct bios_args {
85 };
86 
87 struct bios_return {
90 };
91 
97 };
98 
104 };
105 
106 #define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \
107  != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD))
108 #define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
109 
120 };
121 
122 /* 7 devices fit into the 128 byte buffer */
123 #define HPWMI_MAX_RFKILL2_DEVICES 7
124 
128  u8 pad[8];
130 };
131 
132 static const struct key_entry hp_wmi_keymap[] = {
133  { KE_KEY, 0x02, { KEY_BRIGHTNESSUP } },
134  { KE_KEY, 0x03, { KEY_BRIGHTNESSDOWN } },
135  { KE_KEY, 0x20e6, { KEY_PROG1 } },
136  { KE_KEY, 0x20e8, { KEY_MEDIA } },
137  { KE_KEY, 0x2142, { KEY_MEDIA } },
138  { KE_KEY, 0x213b, { KEY_INFO } },
139  { KE_KEY, 0x2169, { KEY_DIRECTION } },
140  { KE_KEY, 0x231b, { KEY_HELP } },
141  { KE_END, 0 }
142 };
143 
144 static struct input_dev *hp_wmi_input_dev;
145 static struct platform_device *hp_wmi_platform_dev;
146 
147 static struct rfkill *wifi_rfkill;
148 static struct rfkill *bluetooth_rfkill;
149 static struct rfkill *wwan_rfkill;
150 
153  int num;
154  struct rfkill *rfkill;
155 };
156 
157 static int rfkill2_count;
158 static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
159 
160 static const struct dev_pm_ops hp_wmi_pm_ops = {
161  .resume = hp_wmi_resume_handler,
162  .restore = hp_wmi_resume_handler,
163 };
164 
165 static struct platform_driver hp_wmi_driver = {
166  .driver = {
167  .name = "hp-wmi",
168  .owner = THIS_MODULE,
169  .pm = &hp_wmi_pm_ops,
170  },
171  .probe = hp_wmi_bios_setup,
172  .remove = hp_wmi_bios_remove,
173 };
174 
175 /*
176  * hp_wmi_perform_query
177  *
178  * query: The commandtype -> What should be queried
179  * write: The command -> 0 read, 1 write, 3 ODM specific
180  * buffer: Buffer used as input and/or output
181  * insize: Size of input buffer
182  * outsize: Size of output buffer
183  *
184  * returns zero on success
185  * an HP WMI query specific error code (which is positive)
186  * -EINVAL if the query was not successful at all
187  * -EINVAL if the output buffer size exceeds buffersize
188  *
189  * Note: The buffersize must at least be the maximum of the input and output
190  * size. E.g. Battery info query (0x7) is defined to have 1 byte input
191  * and 128 byte output. The caller would do:
192  * buffer = kzalloc(128, GFP_KERNEL);
193  * ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128)
194  */
195 static int hp_wmi_perform_query(int query, int write, void *buffer,
196  int insize, int outsize)
197 {
198  struct bios_return *bios_return;
199  int actual_outsize;
200  union acpi_object *obj;
201  struct bios_args args = {
202  .signature = 0x55434553,
203  .command = write ? 0x2 : 0x1,
204  .commandtype = query,
205  .datasize = insize,
206  .data = 0,
207  };
208  struct acpi_buffer input = { sizeof(struct bios_args), &args };
210  u32 rc;
211 
212  if (WARN_ON(insize > sizeof(args.data)))
213  return -EINVAL;
214  memcpy(&args.data, buffer, insize);
215 
216  wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
217 
218  obj = output.pointer;
219 
220  if (!obj)
221  return -EINVAL;
222  else if (obj->type != ACPI_TYPE_BUFFER) {
223  kfree(obj);
224  return -EINVAL;
225  }
226 
227  bios_return = (struct bios_return *)obj->buffer.pointer;
228  rc = bios_return->return_code;
229 
230  if (rc) {
231  if (rc != HPWMI_RET_UNKNOWN_CMDTYPE)
232  pr_warn("query 0x%x returned error 0x%x\n", query, rc);
233  kfree(obj);
234  return rc;
235  }
236 
237  if (!outsize) {
238  /* ignore output data */
239  kfree(obj);
240  return 0;
241  }
242 
243  actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
244  memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
245  memset(buffer + actual_outsize, 0, outsize - actual_outsize);
246  kfree(obj);
247  return 0;
248 }
249 
250 static int hp_wmi_display_state(void)
251 {
252  int state = 0;
253  int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state,
254  sizeof(state), sizeof(state));
255  if (ret)
256  return -EINVAL;
257  return state;
258 }
259 
260 static int hp_wmi_hddtemp_state(void)
261 {
262  int state = 0;
263  int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state,
264  sizeof(state), sizeof(state));
265  if (ret)
266  return -EINVAL;
267  return state;
268 }
269 
270 static int hp_wmi_als_state(void)
271 {
272  int state = 0;
273  int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state,
274  sizeof(state), sizeof(state));
275  if (ret)
276  return -EINVAL;
277  return state;
278 }
279 
280 static int hp_wmi_dock_state(void)
281 {
282  int state = 0;
283  int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
284  sizeof(state), sizeof(state));
285 
286  if (ret)
287  return -EINVAL;
288 
289  return state & 0x1;
290 }
291 
292 static int hp_wmi_tablet_state(void)
293 {
294  int state = 0;
295  int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
296  sizeof(state), sizeof(state));
297  if (ret)
298  return ret;
299 
300  return (state & 0x4) ? 1 : 0;
301 }
302 
303 static int hp_wmi_set_block(void *data, bool blocked)
304 {
305  enum hp_wmi_radio r = (enum hp_wmi_radio) data;
306  int query = BIT(r + 8) | ((!blocked) << r);
307  int ret;
308 
309  ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1,
310  &query, sizeof(query), 0);
311  if (ret)
312  return -EINVAL;
313  return 0;
314 }
315 
316 static const struct rfkill_ops hp_wmi_rfkill_ops = {
317  .set_block = hp_wmi_set_block,
318 };
319 
320 static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
321 {
322  int wireless = 0;
323  int mask;
324  hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
325  &wireless, sizeof(wireless),
326  sizeof(wireless));
327  /* TBD: Pass error */
328 
329  mask = 0x200 << (r * 8);
330 
331  if (wireless & mask)
332  return false;
333  else
334  return true;
335 }
336 
337 static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
338 {
339  int wireless = 0;
340  int mask;
341  hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
342  &wireless, sizeof(wireless),
343  sizeof(wireless));
344  /* TBD: Pass error */
345 
346  mask = 0x800 << (r * 8);
347 
348  if (wireless & mask)
349  return false;
350  else
351  return true;
352 }
353 
354 static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
355 {
356  int rfkill_id = (int)(long)data;
357  char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
358 
359  if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1,
360  buffer, sizeof(buffer), 0))
361  return -EINVAL;
362  return 0;
363 }
364 
365 static const struct rfkill_ops hp_wmi_rfkill2_ops = {
366  .set_block = hp_wmi_rfkill2_set_block,
367 };
368 
369 static int hp_wmi_rfkill2_refresh(void)
370 {
371  int err, i;
372  struct bios_rfkill2_state state;
373 
374  err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
375  0, sizeof(state));
376  if (err)
377  return err;
378 
379  for (i = 0; i < rfkill2_count; i++) {
380  int num = rfkill2[i].num;
381  struct bios_rfkill2_device_state *devstate;
382  devstate = &state.device[num];
383 
384  if (num >= state.count ||
385  devstate->rfkill_id != rfkill2[i].id) {
386  pr_warn("power configuration of the wireless devices unexpectedly changed\n");
387  continue;
388  }
389 
390  rfkill_set_states(rfkill2[i].rfkill,
391  IS_SWBLOCKED(devstate->power),
392  IS_HWBLOCKED(devstate->power));
393  }
394 
395  return 0;
396 }
397 
398 static ssize_t show_display(struct device *dev, struct device_attribute *attr,
399  char *buf)
400 {
401  int value = hp_wmi_display_state();
402  if (value < 0)
403  return -EINVAL;
404  return sprintf(buf, "%d\n", value);
405 }
406 
407 static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr,
408  char *buf)
409 {
410  int value = hp_wmi_hddtemp_state();
411  if (value < 0)
412  return -EINVAL;
413  return sprintf(buf, "%d\n", value);
414 }
415 
416 static ssize_t show_als(struct device *dev, struct device_attribute *attr,
417  char *buf)
418 {
419  int value = hp_wmi_als_state();
420  if (value < 0)
421  return -EINVAL;
422  return sprintf(buf, "%d\n", value);
423 }
424 
425 static ssize_t show_dock(struct device *dev, struct device_attribute *attr,
426  char *buf)
427 {
428  int value = hp_wmi_dock_state();
429  if (value < 0)
430  return -EINVAL;
431  return sprintf(buf, "%d\n", value);
432 }
433 
434 static ssize_t show_tablet(struct device *dev, struct device_attribute *attr,
435  char *buf)
436 {
437  int value = hp_wmi_tablet_state();
438  if (value < 0)
439  return -EINVAL;
440  return sprintf(buf, "%d\n", value);
441 }
442 
443 static ssize_t set_als(struct device *dev, struct device_attribute *attr,
444  const char *buf, size_t count)
445 {
446  u32 tmp = simple_strtoul(buf, NULL, 10);
447  int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp,
448  sizeof(tmp), sizeof(tmp));
449  if (ret)
450  return -EINVAL;
451 
452  return count;
453 }
454 
455 static DEVICE_ATTR(display, S_IRUGO, show_display, NULL);
456 static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL);
457 static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
458 static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
459 static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
460 
461 static void hp_wmi_notify(u32 value, void *context)
462 {
464  union acpi_object *obj;
466  int key_code = 0, ret;
467  u32 *location;
469 
470  status = wmi_get_event_data(value, &response);
471  if (status != AE_OK) {
472  pr_info("bad event status 0x%x\n", status);
473  return;
474  }
475 
476  obj = (union acpi_object *)response.pointer;
477 
478  if (!obj)
479  return;
480  if (obj->type != ACPI_TYPE_BUFFER) {
481  pr_info("Unknown response received %d\n", obj->type);
482  kfree(obj);
483  return;
484  }
485 
486  /*
487  * Depending on ACPI version the concatenation of id and event data
488  * inside _WED function will result in a 8 or 16 byte buffer.
489  */
490  location = (u32 *)obj->buffer.pointer;
491  if (obj->buffer.length == 8) {
492  event_id = *location;
493  event_data = *(location + 1);
494  } else if (obj->buffer.length == 16) {
495  event_id = *location;
496  event_data = *(location + 2);
497  } else {
498  pr_info("Unknown buffer length %d\n", obj->buffer.length);
499  kfree(obj);
500  return;
501  }
502  kfree(obj);
503 
504  switch (event_id) {
505  case HPWMI_DOCK_EVENT:
506  input_report_switch(hp_wmi_input_dev, SW_DOCK,
507  hp_wmi_dock_state());
508  input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
509  hp_wmi_tablet_state());
510  input_sync(hp_wmi_input_dev);
511  break;
512  case HPWMI_PARK_HDD:
513  break;
514  case HPWMI_SMART_ADAPTER:
515  break;
516  case HPWMI_BEZEL_BUTTON:
517  ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
518  &key_code,
519  sizeof(key_code),
520  sizeof(key_code));
521  if (ret)
522  break;
523 
524  if (!sparse_keymap_report_event(hp_wmi_input_dev,
525  key_code, 1, true))
526  pr_info("Unknown key code - 0x%x\n", key_code);
527  break;
528  case HPWMI_WIRELESS:
529  if (rfkill2_count) {
530  hp_wmi_rfkill2_refresh();
531  break;
532  }
533 
534  if (wifi_rfkill)
535  rfkill_set_states(wifi_rfkill,
536  hp_wmi_get_sw_state(HPWMI_WIFI),
537  hp_wmi_get_hw_state(HPWMI_WIFI));
538  if (bluetooth_rfkill)
539  rfkill_set_states(bluetooth_rfkill,
540  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
541  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
542  if (wwan_rfkill)
543  rfkill_set_states(wwan_rfkill,
544  hp_wmi_get_sw_state(HPWMI_WWAN),
545  hp_wmi_get_hw_state(HPWMI_WWAN));
546  break;
548  pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
549  break;
550  case HPWMI_LOCK_SWITCH:
551  break;
552  default:
553  pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
554  break;
555  }
556 }
557 
558 static int __init hp_wmi_input_setup(void)
559 {
561  int err;
562 
563  hp_wmi_input_dev = input_allocate_device();
564  if (!hp_wmi_input_dev)
565  return -ENOMEM;
566 
567  hp_wmi_input_dev->name = "HP WMI hotkeys";
568  hp_wmi_input_dev->phys = "wmi/input0";
569  hp_wmi_input_dev->id.bustype = BUS_HOST;
570 
571  __set_bit(EV_SW, hp_wmi_input_dev->evbit);
572  __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
573  __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
574 
575  err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
576  if (err)
577  goto err_free_dev;
578 
579  /* Set initial hardware state */
580  input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
581  input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
582  hp_wmi_tablet_state());
583  input_sync(hp_wmi_input_dev);
584 
585  status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
586  if (ACPI_FAILURE(status)) {
587  err = -EIO;
588  goto err_free_keymap;
589  }
590 
591  err = input_register_device(hp_wmi_input_dev);
592  if (err)
593  goto err_uninstall_notifier;
594 
595  return 0;
596 
597  err_uninstall_notifier:
599  err_free_keymap:
600  sparse_keymap_free(hp_wmi_input_dev);
601  err_free_dev:
602  input_free_device(hp_wmi_input_dev);
603  return err;
604 }
605 
606 static void hp_wmi_input_destroy(void)
607 {
609  sparse_keymap_free(hp_wmi_input_dev);
610  input_unregister_device(hp_wmi_input_dev);
611 }
612 
613 static void cleanup_sysfs(struct platform_device *device)
614 {
615  device_remove_file(&device->dev, &dev_attr_display);
616  device_remove_file(&device->dev, &dev_attr_hddtemp);
617  device_remove_file(&device->dev, &dev_attr_als);
618  device_remove_file(&device->dev, &dev_attr_dock);
619  device_remove_file(&device->dev, &dev_attr_tablet);
620 }
621 
622 static int __devinit hp_wmi_rfkill_setup(struct platform_device *device)
623 {
624  int err;
625  int wireless = 0;
626 
627  err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless,
628  sizeof(wireless), sizeof(wireless));
629  if (err)
630  return err;
631 
632  if (wireless & 0x1) {
633  wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
635  &hp_wmi_rfkill_ops,
636  (void *) HPWMI_WIFI);
637  if (!wifi_rfkill)
638  return -ENOMEM;
639  rfkill_init_sw_state(wifi_rfkill,
640  hp_wmi_get_sw_state(HPWMI_WIFI));
641  rfkill_set_hw_state(wifi_rfkill,
642  hp_wmi_get_hw_state(HPWMI_WIFI));
643  err = rfkill_register(wifi_rfkill);
644  if (err)
645  goto register_wifi_error;
646  }
647 
648  if (wireless & 0x2) {
649  bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
651  &hp_wmi_rfkill_ops,
652  (void *) HPWMI_BLUETOOTH);
653  if (!bluetooth_rfkill) {
654  err = -ENOMEM;
655  goto register_wifi_error;
656  }
657  rfkill_init_sw_state(bluetooth_rfkill,
658  hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
659  rfkill_set_hw_state(bluetooth_rfkill,
660  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
661  err = rfkill_register(bluetooth_rfkill);
662  if (err)
663  goto register_bluetooth_error;
664  }
665 
666  if (wireless & 0x4) {
667  wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
669  &hp_wmi_rfkill_ops,
670  (void *) HPWMI_WWAN);
671  if (!wwan_rfkill) {
672  err = -ENOMEM;
673  goto register_bluetooth_error;
674  }
675  rfkill_init_sw_state(wwan_rfkill,
676  hp_wmi_get_sw_state(HPWMI_WWAN));
677  rfkill_set_hw_state(wwan_rfkill,
678  hp_wmi_get_hw_state(HPWMI_WWAN));
679  err = rfkill_register(wwan_rfkill);
680  if (err)
681  goto register_wwan_err;
682  }
683 
684  return 0;
685 register_wwan_err:
686  rfkill_destroy(wwan_rfkill);
687  wwan_rfkill = NULL;
688  if (bluetooth_rfkill)
689  rfkill_unregister(bluetooth_rfkill);
690 register_bluetooth_error:
691  rfkill_destroy(bluetooth_rfkill);
692  bluetooth_rfkill = NULL;
693  if (wifi_rfkill)
694  rfkill_unregister(wifi_rfkill);
695 register_wifi_error:
696  rfkill_destroy(wifi_rfkill);
697  wifi_rfkill = NULL;
698  return err;
699 }
700 
701 static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device)
702 {
703  int err, i;
704  struct bios_rfkill2_state state;
705  err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
706  0, sizeof(state));
707  if (err)
708  return err;
709 
710  if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
711  pr_warn("unable to parse 0x1b query output\n");
712  return -EINVAL;
713  }
714 
715  for (i = 0; i < state.count; i++) {
716  struct rfkill *rfkill;
717  enum rfkill_type type;
718  char *name;
719  switch (state.device[i].radio_type) {
720  case HPWMI_WIFI:
721  type = RFKILL_TYPE_WLAN;
722  name = "hp-wifi";
723  break;
724  case HPWMI_BLUETOOTH:
725  type = RFKILL_TYPE_BLUETOOTH;
726  name = "hp-bluetooth";
727  break;
728  case HPWMI_WWAN:
729  type = RFKILL_TYPE_WWAN;
730  name = "hp-wwan";
731  break;
732  default:
733  pr_warn("unknown device type 0x%x\n",
734  state.device[i].radio_type);
735  continue;
736  }
737 
738  if (!state.device[i].vendor_id) {
739  pr_warn("zero device %d while %d reported\n",
740  i, state.count);
741  continue;
742  }
743 
744  rfkill = rfkill_alloc(name, &device->dev, type,
745  &hp_wmi_rfkill2_ops, (void *)(long)i);
746  if (!rfkill) {
747  err = -ENOMEM;
748  goto fail;
749  }
750 
751  rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
752  rfkill2[rfkill2_count].num = i;
753  rfkill2[rfkill2_count].rfkill = rfkill;
754 
755  rfkill_init_sw_state(rfkill,
756  IS_SWBLOCKED(state.device[i].power));
757  rfkill_set_hw_state(rfkill,
758  IS_HWBLOCKED(state.device[i].power));
759 
760  if (!(state.device[i].power & HPWMI_POWER_BIOS))
761  pr_info("device %s blocked by BIOS\n", name);
762 
763  err = rfkill_register(rfkill);
764  if (err) {
765  rfkill_destroy(rfkill);
766  goto fail;
767  }
768 
769  rfkill2_count++;
770  }
771 
772  return 0;
773 fail:
774  for (; rfkill2_count > 0; rfkill2_count--) {
775  rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
776  rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
777  }
778  return err;
779 }
780 
781 static int __devinit hp_wmi_bios_setup(struct platform_device *device)
782 {
783  int err;
784 
785  /* clear detected rfkill devices */
786  wifi_rfkill = NULL;
787  bluetooth_rfkill = NULL;
788  wwan_rfkill = NULL;
789  rfkill2_count = 0;
790 
791  if (hp_wmi_rfkill_setup(device))
792  hp_wmi_rfkill2_setup(device);
793 
794  err = device_create_file(&device->dev, &dev_attr_display);
795  if (err)
796  goto add_sysfs_error;
797  err = device_create_file(&device->dev, &dev_attr_hddtemp);
798  if (err)
799  goto add_sysfs_error;
800  err = device_create_file(&device->dev, &dev_attr_als);
801  if (err)
802  goto add_sysfs_error;
803  err = device_create_file(&device->dev, &dev_attr_dock);
804  if (err)
805  goto add_sysfs_error;
806  err = device_create_file(&device->dev, &dev_attr_tablet);
807  if (err)
808  goto add_sysfs_error;
809  return 0;
810 
811 add_sysfs_error:
812  cleanup_sysfs(device);
813  return err;
814 }
815 
816 static int __exit hp_wmi_bios_remove(struct platform_device *device)
817 {
818  int i;
819  cleanup_sysfs(device);
820 
821  for (i = 0; i < rfkill2_count; i++) {
822  rfkill_unregister(rfkill2[i].rfkill);
823  rfkill_destroy(rfkill2[i].rfkill);
824  }
825 
826  if (wifi_rfkill) {
827  rfkill_unregister(wifi_rfkill);
828  rfkill_destroy(wifi_rfkill);
829  }
830  if (bluetooth_rfkill) {
831  rfkill_unregister(bluetooth_rfkill);
832  rfkill_destroy(bluetooth_rfkill);
833  }
834  if (wwan_rfkill) {
835  rfkill_unregister(wwan_rfkill);
836  rfkill_destroy(wwan_rfkill);
837  }
838 
839  return 0;
840 }
841 
842 static int hp_wmi_resume_handler(struct device *device)
843 {
844  /*
845  * Hardware state may have changed while suspended, so trigger
846  * input events for the current state. As this is a switch,
847  * the input layer will only actually pass it on if the state
848  * changed.
849  */
850  if (hp_wmi_input_dev) {
851  input_report_switch(hp_wmi_input_dev, SW_DOCK,
852  hp_wmi_dock_state());
853  input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
854  hp_wmi_tablet_state());
855  input_sync(hp_wmi_input_dev);
856  }
857 
858  if (rfkill2_count)
859  hp_wmi_rfkill2_refresh();
860 
861  if (wifi_rfkill)
862  rfkill_set_states(wifi_rfkill,
863  hp_wmi_get_sw_state(HPWMI_WIFI),
864  hp_wmi_get_hw_state(HPWMI_WIFI));
865  if (bluetooth_rfkill)
866  rfkill_set_states(bluetooth_rfkill,
867  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
868  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
869  if (wwan_rfkill)
870  rfkill_set_states(wwan_rfkill,
871  hp_wmi_get_sw_state(HPWMI_WWAN),
872  hp_wmi_get_hw_state(HPWMI_WWAN));
873 
874  return 0;
875 }
876 
877 static int __init hp_wmi_init(void)
878 {
879  int err;
880  int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
881  int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
882 
883  if (event_capable) {
884  err = hp_wmi_input_setup();
885  if (err)
886  return err;
887  }
888 
889  if (bios_capable) {
890  err = platform_driver_register(&hp_wmi_driver);
891  if (err)
892  goto err_driver_reg;
893  hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1);
894  if (!hp_wmi_platform_dev) {
895  err = -ENOMEM;
896  goto err_device_alloc;
897  }
898  err = platform_device_add(hp_wmi_platform_dev);
899  if (err)
900  goto err_device_add;
901  }
902 
903  if (!bios_capable && !event_capable)
904  return -ENODEV;
905 
906  return 0;
907 
908 err_device_add:
909  platform_device_put(hp_wmi_platform_dev);
910 err_device_alloc:
911  platform_driver_unregister(&hp_wmi_driver);
912 err_driver_reg:
913  if (event_capable)
914  hp_wmi_input_destroy();
915 
916  return err;
917 }
918 
919 static void __exit hp_wmi_exit(void)
920 {
922  hp_wmi_input_destroy();
923 
924  if (hp_wmi_platform_dev) {
925  platform_device_unregister(hp_wmi_platform_dev);
926  platform_driver_unregister(&hp_wmi_driver);
927  }
928 }
929 
930 module_init(hp_wmi_init);
931 module_exit(hp_wmi_exit);