1 /* 2 * Eee PC WMI hotkey driver 3 * 4 * Copyright(C) 2010 Intel Corporation. 5 * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com> 6 * 7 * Portions based on wistron_btns.c: 8 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> 9 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> 10 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> 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/types.h> 33 #include <linux/slab.h> 34 #include <linux/input.h> 35 #include <linux/input/sparse-keymap.h> 36 #include <linux/fb.h> 37 #include <linux/backlight.h> 38 #include <linux/leds.h> 39 #include <linux/rfkill.h> 40 #include <linux/debugfs.h> 41 #include <linux/seq_file.h> 42 #include <linux/platform_device.h> 43 #include <acpi/acpi_bus.h> 44 #include <acpi/acpi_drivers.h> 45 46 #define EEEPC_WMI_FILE "eeepc-wmi" 47 48 MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); 49 MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); 50 MODULE_LICENSE("GPL"); 51 52 #define EEEPC_ACPI_HID "ASUS010" /* old _HID used in eeepc-laptop */ 53 54 #define EEEPC_WMI_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000" 55 #define EEEPC_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66" 56 57 MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID); 58 MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID); 59 60 #define NOTIFY_BRNUP_MIN 0x11 61 #define NOTIFY_BRNUP_MAX 0x1f 62 #define NOTIFY_BRNDOWN_MIN 0x20 63 #define NOTIFY_BRNDOWN_MAX 0x2e 64 65 #define EEEPC_WMI_METHODID_DEVS 0x53564544 66 #define EEEPC_WMI_METHODID_DSTS 0x53544344 67 #define EEEPC_WMI_METHODID_CFVS 0x53564643 68 69 #define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 70 #define EEEPC_WMI_DEVID_TPDLED 0x00100011 71 #define EEEPC_WMI_DEVID_WLAN 0x00010011 72 #define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013 73 #define EEEPC_WMI_DEVID_WWAN3G 0x00010019 74 75 static const struct key_entry eeepc_wmi_keymap[] = { 76 /* Sleep already handled via generic ACPI code */ 77 { KE_KEY, 0x5d, { KEY_WLAN } }, 78 { KE_KEY, 0x32, { KEY_MUTE } }, 79 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, 80 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 81 { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } }, 82 { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } }, 83 { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } }, 84 { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */ 85 { KE_KEY, 0xe1, { KEY_F14 } }, 86 { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } }, 87 { KE_KEY, 0xe0, { KEY_PROG1 } }, 88 { KE_KEY, 0x5c, { KEY_F15 } }, 89 { KE_END, 0}, 90 }; 91 92 struct bios_args { 93 u32 dev_id; 94 u32 ctrl_param; 95 }; 96 97 /* 98 * eeepc-wmi/ - debugfs root directory 99 * dev_id - current dev_id 100 * ctrl_param - current ctrl_param 101 * devs - call DEVS(dev_id, ctrl_param) and print result 102 * dsts - call DSTS(dev_id) and print result 103 */ 104 struct eeepc_wmi_debug { 105 struct dentry *root; 106 u32 dev_id; 107 u32 ctrl_param; 108 }; 109 110 struct eeepc_wmi { 111 struct input_dev *inputdev; 112 struct backlight_device *backlight_device; 113 struct platform_device *platform_device; 114 115 struct led_classdev tpd_led; 116 int tpd_led_wk; 117 struct workqueue_struct *led_workqueue; 118 struct work_struct tpd_led_work; 119 120 struct rfkill *wlan_rfkill; 121 struct rfkill *bluetooth_rfkill; 122 struct rfkill *wwan3g_rfkill; 123 124 struct eeepc_wmi_debug debug; 125 }; 126 127 /* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */ 128 static struct platform_device *platform_device; 129 130 static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc) 131 { 132 int err; 133 134 eeepc->inputdev = input_allocate_device(); 135 if (!eeepc->inputdev) 136 return -ENOMEM; 137 138 eeepc->inputdev->name = "Eee PC WMI hotkeys"; 139 eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0"; 140 eeepc->inputdev->id.bustype = BUS_HOST; 141 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; 142 143 err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL); 144 if (err) 145 goto err_free_dev; 146 147 err = input_register_device(eeepc->inputdev); 148 if (err) 149 goto err_free_keymap; 150 151 return 0; 152 153 err_free_keymap: 154 sparse_keymap_free(eeepc->inputdev); 155 err_free_dev: 156 input_free_device(eeepc->inputdev); 157 return err; 158 } 159 160 static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc) 161 { 162 if (eeepc->inputdev) { 163 sparse_keymap_free(eeepc->inputdev); 164 input_unregister_device(eeepc->inputdev); 165 } 166 167 eeepc->inputdev = NULL; 168 } 169 170 static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval) 171 { 172 struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id }; 173 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 174 union acpi_object *obj; 175 acpi_status status; 176 u32 tmp; 177 178 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 179 1, EEEPC_WMI_METHODID_DSTS, &input, &output); 180 181 if (ACPI_FAILURE(status)) 182 return status; 183 184 obj = (union acpi_object *)output.pointer; 185 if (obj && obj->type == ACPI_TYPE_INTEGER) 186 tmp = (u32)obj->integer.value; 187 else 188 tmp = 0; 189 190 if (retval) 191 *retval = tmp; 192 193 kfree(obj); 194 195 return status; 196 197 } 198 199 static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param, 200 u32 *retval) 201 { 202 struct bios_args args = { 203 .dev_id = dev_id, 204 .ctrl_param = ctrl_param, 205 }; 206 struct acpi_buffer input = { (acpi_size)sizeof(args), &args }; 207 acpi_status status; 208 209 if (!retval) { 210 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1, 211 EEEPC_WMI_METHODID_DEVS, 212 &input, NULL); 213 } else { 214 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 215 union acpi_object *obj; 216 u32 tmp; 217 218 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1, 219 EEEPC_WMI_METHODID_DEVS, 220 &input, &output); 221 222 if (ACPI_FAILURE(status)) 223 return status; 224 225 obj = (union acpi_object *)output.pointer; 226 if (obj && obj->type == ACPI_TYPE_INTEGER) 227 tmp = (u32)obj->integer.value; 228 else 229 tmp = 0; 230 231 *retval = tmp; 232 233 kfree(obj); 234 } 235 236 return status; 237 } 238 239 /* 240 * LEDs 241 */ 242 /* 243 * These functions actually update the LED's, and are called from a 244 * workqueue. By doing this as separate work rather than when the LED 245 * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a 246 * potentially bad time, such as a timer interrupt. 247 */ 248 static void tpd_led_update(struct work_struct *work) 249 { 250 int ctrl_param; 251 struct eeepc_wmi *eeepc; 252 253 eeepc = container_of(work, struct eeepc_wmi, tpd_led_work); 254 255 ctrl_param = eeepc->tpd_led_wk; 256 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL); 257 } 258 259 static void tpd_led_set(struct led_classdev *led_cdev, 260 enum led_brightness value) 261 { 262 struct eeepc_wmi *eeepc; 263 264 eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led); 265 266 eeepc->tpd_led_wk = !!value; 267 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work); 268 } 269 270 static int read_tpd_state(struct eeepc_wmi *eeepc) 271 { 272 u32 retval; 273 acpi_status status; 274 275 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED, &retval); 276 277 if (ACPI_FAILURE(status)) 278 return -1; 279 else if (!retval || retval == 0x00060000) 280 /* 281 * if touchpad led is present, DSTS will set some bits, 282 * usually 0x00020000. 283 * 0x00060000 means that the device is not supported 284 */ 285 return -ENODEV; 286 else 287 /* Status is stored in the first bit */ 288 return retval & 0x1; 289 } 290 291 static enum led_brightness tpd_led_get(struct led_classdev *led_cdev) 292 { 293 struct eeepc_wmi *eeepc; 294 295 eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led); 296 297 return read_tpd_state(eeepc); 298 } 299 300 static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc) 301 { 302 int rv; 303 304 if (read_tpd_state(eeepc) < 0) 305 return 0; 306 307 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue"); 308 if (!eeepc->led_workqueue) 309 return -ENOMEM; 310 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update); 311 312 eeepc->tpd_led.name = "eeepc::touchpad"; 313 eeepc->tpd_led.brightness_set = tpd_led_set; 314 eeepc->tpd_led.brightness_get = tpd_led_get; 315 eeepc->tpd_led.max_brightness = 1; 316 317 rv = led_classdev_register(&eeepc->platform_device->dev, 318 &eeepc->tpd_led); 319 if (rv) { 320 destroy_workqueue(eeepc->led_workqueue); 321 return rv; 322 } 323 324 return 0; 325 } 326 327 static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc) 328 { 329 if (eeepc->tpd_led.dev) 330 led_classdev_unregister(&eeepc->tpd_led); 331 if (eeepc->led_workqueue) 332 destroy_workqueue(eeepc->led_workqueue); 333 } 334 335 /* 336 * Rfkill devices 337 */ 338 static int eeepc_rfkill_set(void *data, bool blocked) 339 { 340 int dev_id = (unsigned long)data; 341 u32 ctrl_param = !blocked; 342 343 return eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL); 344 } 345 346 static void eeepc_rfkill_query(struct rfkill *rfkill, void *data) 347 { 348 int dev_id = (unsigned long)data; 349 u32 retval; 350 acpi_status status; 351 352 status = eeepc_wmi_get_devstate(dev_id, &retval); 353 354 if (ACPI_FAILURE(status)) 355 return ; 356 357 rfkill_set_sw_state(rfkill, !(retval & 0x1)); 358 } 359 360 static const struct rfkill_ops eeepc_rfkill_ops = { 361 .set_block = eeepc_rfkill_set, 362 .query = eeepc_rfkill_query, 363 }; 364 365 static int eeepc_new_rfkill(struct eeepc_wmi *eeepc, 366 struct rfkill **rfkill, 367 const char *name, 368 enum rfkill_type type, int dev_id) 369 { 370 int result; 371 u32 retval; 372 acpi_status status; 373 374 status = eeepc_wmi_get_devstate(dev_id, &retval); 375 376 if (ACPI_FAILURE(status)) 377 return -1; 378 379 /* If the device is present, DSTS will always set some bits 380 * 0x00070000 - 1110000000000000000 - device supported 381 * 0x00060000 - 1100000000000000000 - not supported 382 * 0x00020000 - 0100000000000000000 - device supported 383 * 0x00010000 - 0010000000000000000 - not supported / special mode ? 384 */ 385 if (!retval || retval == 0x00060000) 386 return -ENODEV; 387 388 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type, 389 &eeepc_rfkill_ops, (void *)(long)dev_id); 390 391 if (!*rfkill) 392 return -EINVAL; 393 394 rfkill_init_sw_state(*rfkill, !(retval & 0x1)); 395 result = rfkill_register(*rfkill); 396 if (result) { 397 rfkill_destroy(*rfkill); 398 *rfkill = NULL; 399 return result; 400 } 401 return 0; 402 } 403 404 static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc) 405 { 406 if (eeepc->wlan_rfkill) { 407 rfkill_unregister(eeepc->wlan_rfkill); 408 rfkill_destroy(eeepc->wlan_rfkill); 409 eeepc->wlan_rfkill = NULL; 410 } 411 if (eeepc->bluetooth_rfkill) { 412 rfkill_unregister(eeepc->bluetooth_rfkill); 413 rfkill_destroy(eeepc->bluetooth_rfkill); 414 eeepc->bluetooth_rfkill = NULL; 415 } 416 if (eeepc->wwan3g_rfkill) { 417 rfkill_unregister(eeepc->wwan3g_rfkill); 418 rfkill_destroy(eeepc->wwan3g_rfkill); 419 eeepc->wwan3g_rfkill = NULL; 420 } 421 } 422 423 static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc) 424 { 425 int result = 0; 426 427 result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill, 428 "eeepc-wlan", RFKILL_TYPE_WLAN, 429 EEEPC_WMI_DEVID_WLAN); 430 431 if (result && result != -ENODEV) 432 goto exit; 433 434 result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill, 435 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH, 436 EEEPC_WMI_DEVID_BLUETOOTH); 437 438 if (result && result != -ENODEV) 439 goto exit; 440 441 result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill, 442 "eeepc-wwan3g", RFKILL_TYPE_WWAN, 443 EEEPC_WMI_DEVID_WWAN3G); 444 445 if (result && result != -ENODEV) 446 goto exit; 447 448 exit: 449 if (result && result != -ENODEV) 450 eeepc_wmi_rfkill_exit(eeepc); 451 452 if (result == -ENODEV) 453 result = 0; 454 455 return result; 456 } 457 458 /* 459 * Backlight 460 */ 461 static int read_brightness(struct backlight_device *bd) 462 { 463 u32 retval; 464 acpi_status status; 465 466 status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval); 467 468 if (ACPI_FAILURE(status)) 469 return -1; 470 else 471 return retval & 0xFF; 472 } 473 474 static int update_bl_status(struct backlight_device *bd) 475 { 476 477 u32 ctrl_param; 478 acpi_status status; 479 480 ctrl_param = bd->props.brightness; 481 482 status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT, 483 ctrl_param, NULL); 484 485 if (ACPI_FAILURE(status)) 486 return -1; 487 else 488 return 0; 489 } 490 491 static const struct backlight_ops eeepc_wmi_bl_ops = { 492 .get_brightness = read_brightness, 493 .update_status = update_bl_status, 494 }; 495 496 static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code) 497 { 498 struct backlight_device *bd = eeepc->backlight_device; 499 int old = bd->props.brightness; 500 int new = old; 501 502 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) 503 new = code - NOTIFY_BRNUP_MIN + 1; 504 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX) 505 new = code - NOTIFY_BRNDOWN_MIN; 506 507 bd->props.brightness = new; 508 backlight_update_status(bd); 509 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY); 510 511 return old; 512 } 513 514 static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc) 515 { 516 struct backlight_device *bd; 517 struct backlight_properties props; 518 519 memset(&props, 0, sizeof(struct backlight_properties)); 520 props.max_brightness = 15; 521 bd = backlight_device_register(EEEPC_WMI_FILE, 522 &eeepc->platform_device->dev, eeepc, 523 &eeepc_wmi_bl_ops, &props); 524 if (IS_ERR(bd)) { 525 pr_err("Could not register backlight device\n"); 526 return PTR_ERR(bd); 527 } 528 529 eeepc->backlight_device = bd; 530 531 bd->props.brightness = read_brightness(bd); 532 bd->props.power = FB_BLANK_UNBLANK; 533 backlight_update_status(bd); 534 535 return 0; 536 } 537 538 static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc) 539 { 540 if (eeepc->backlight_device) 541 backlight_device_unregister(eeepc->backlight_device); 542 543 eeepc->backlight_device = NULL; 544 } 545 546 static void eeepc_wmi_notify(u32 value, void *context) 547 { 548 struct eeepc_wmi *eeepc = context; 549 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 550 union acpi_object *obj; 551 acpi_status status; 552 int code; 553 int orig_code; 554 555 status = wmi_get_event_data(value, &response); 556 if (status != AE_OK) { 557 pr_err("bad event status 0x%x\n", status); 558 return; 559 } 560 561 obj = (union acpi_object *)response.pointer; 562 563 if (obj && obj->type == ACPI_TYPE_INTEGER) { 564 code = obj->integer.value; 565 orig_code = code; 566 567 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) 568 code = NOTIFY_BRNUP_MIN; 569 else if (code >= NOTIFY_BRNDOWN_MIN && 570 code <= NOTIFY_BRNDOWN_MAX) 571 code = NOTIFY_BRNDOWN_MIN; 572 573 if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) { 574 if (!acpi_video_backlight_support()) 575 eeepc_wmi_backlight_notify(eeepc, orig_code); 576 } 577 578 if (!sparse_keymap_report_event(eeepc->inputdev, 579 code, 1, true)) 580 pr_info("Unknown key %x pressed\n", code); 581 } 582 583 kfree(obj); 584 } 585 586 static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, 587 const char *buf, size_t count) 588 { 589 int value; 590 struct acpi_buffer input = { (acpi_size)sizeof(value), &value }; 591 acpi_status status; 592 593 if (!count || sscanf(buf, "%i", &value) != 1) 594 return -EINVAL; 595 if (value < 0 || value > 2) 596 return -EINVAL; 597 598 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 599 1, EEEPC_WMI_METHODID_CFVS, &input, NULL); 600 601 if (ACPI_FAILURE(status)) 602 return -EIO; 603 else 604 return count; 605 } 606 607 static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); 608 609 static struct attribute *platform_attributes[] = { 610 &dev_attr_cpufv.attr, 611 NULL 612 }; 613 614 static struct attribute_group platform_attribute_group = { 615 .attrs = platform_attributes 616 }; 617 618 static void eeepc_wmi_sysfs_exit(struct platform_device *device) 619 { 620 sysfs_remove_group(&device->dev.kobj, &platform_attribute_group); 621 } 622 623 static int eeepc_wmi_sysfs_init(struct platform_device *device) 624 { 625 return sysfs_create_group(&device->dev.kobj, &platform_attribute_group); 626 } 627 628 /* 629 * Platform device 630 */ 631 static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc) 632 { 633 int err; 634 635 eeepc->platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1); 636 if (!eeepc->platform_device) 637 return -ENOMEM; 638 platform_set_drvdata(eeepc->platform_device, eeepc); 639 640 err = platform_device_add(eeepc->platform_device); 641 if (err) 642 goto fail_platform_device; 643 644 err = eeepc_wmi_sysfs_init(eeepc->platform_device); 645 if (err) 646 goto fail_sysfs; 647 return 0; 648 649 fail_sysfs: 650 platform_device_del(eeepc->platform_device); 651 fail_platform_device: 652 platform_device_put(eeepc->platform_device); 653 return err; 654 } 655 656 static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc) 657 { 658 eeepc_wmi_sysfs_exit(eeepc->platform_device); 659 platform_device_unregister(eeepc->platform_device); 660 } 661 662 /* 663 * debugfs 664 */ 665 struct eeepc_wmi_debugfs_node { 666 struct eeepc_wmi *eeepc; 667 char *name; 668 int (*show)(struct seq_file *m, void *data); 669 }; 670 671 static int show_dsts(struct seq_file *m, void *data) 672 { 673 struct eeepc_wmi *eeepc = m->private; 674 acpi_status status; 675 u32 retval = -1; 676 677 status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval); 678 679 if (ACPI_FAILURE(status)) 680 return -EIO; 681 682 seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval); 683 684 return 0; 685 } 686 687 static int show_devs(struct seq_file *m, void *data) 688 { 689 struct eeepc_wmi *eeepc = m->private; 690 acpi_status status; 691 u32 retval = -1; 692 693 status = eeepc_wmi_set_devstate(eeepc->debug.dev_id, 694 eeepc->debug.ctrl_param, &retval); 695 if (ACPI_FAILURE(status)) 696 return -EIO; 697 698 seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id, 699 eeepc->debug.ctrl_param, retval); 700 701 return 0; 702 } 703 704 static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = { 705 { NULL, "devs", show_devs }, 706 { NULL, "dsts", show_dsts }, 707 }; 708 709 static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file) 710 { 711 struct eeepc_wmi_debugfs_node *node = inode->i_private; 712 713 return single_open(file, node->show, node->eeepc); 714 } 715 716 static const struct file_operations eeepc_wmi_debugfs_io_ops = { 717 .owner = THIS_MODULE, 718 .open = eeepc_wmi_debugfs_open, 719 .read = seq_read, 720 .llseek = seq_lseek, 721 .release = single_release, 722 }; 723 724 static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc) 725 { 726 debugfs_remove_recursive(eeepc->debug.root); 727 } 728 729 static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc) 730 { 731 struct dentry *dent; 732 int i; 733 734 eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL); 735 if (!eeepc->debug.root) { 736 pr_err("failed to create debugfs directory"); 737 goto error_debugfs; 738 } 739 740 dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR, 741 eeepc->debug.root, &eeepc->debug.dev_id); 742 if (!dent) 743 goto error_debugfs; 744 745 dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR, 746 eeepc->debug.root, &eeepc->debug.ctrl_param); 747 if (!dent) 748 goto error_debugfs; 749 750 for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) { 751 struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i]; 752 753 node->eeepc = eeepc; 754 dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO, 755 eeepc->debug.root, node, 756 &eeepc_wmi_debugfs_io_ops); 757 if (!dent) { 758 pr_err("failed to create debug file: %s\n", node->name); 759 goto error_debugfs; 760 } 761 } 762 763 return 0; 764 765 error_debugfs: 766 eeepc_wmi_debugfs_exit(eeepc); 767 return -ENOMEM; 768 } 769 770 /* 771 * WMI Driver 772 */ 773 static struct platform_device * __init eeepc_wmi_add(void) 774 { 775 struct eeepc_wmi *eeepc; 776 acpi_status status; 777 int err; 778 779 eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL); 780 if (!eeepc) 781 return ERR_PTR(-ENOMEM); 782 783 /* 784 * Register the platform device first. It is used as a parent for the 785 * sub-devices below. 786 */ 787 err = eeepc_wmi_platform_init(eeepc); 788 if (err) 789 goto fail_platform; 790 791 err = eeepc_wmi_input_init(eeepc); 792 if (err) 793 goto fail_input; 794 795 err = eeepc_wmi_led_init(eeepc); 796 if (err) 797 goto fail_leds; 798 799 err = eeepc_wmi_rfkill_init(eeepc); 800 if (err) 801 goto fail_rfkill; 802 803 if (!acpi_video_backlight_support()) { 804 err = eeepc_wmi_backlight_init(eeepc); 805 if (err) 806 goto fail_backlight; 807 } else 808 pr_info("Backlight controlled by ACPI video driver\n"); 809 810 status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID, 811 eeepc_wmi_notify, eeepc); 812 if (ACPI_FAILURE(status)) { 813 pr_err("Unable to register notify handler - %d\n", 814 status); 815 err = -ENODEV; 816 goto fail_wmi_handler; 817 } 818 819 err = eeepc_wmi_debugfs_init(eeepc); 820 if (err) 821 goto fail_debugfs; 822 823 return eeepc->platform_device; 824 825 fail_debugfs: 826 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); 827 fail_wmi_handler: 828 eeepc_wmi_backlight_exit(eeepc); 829 fail_backlight: 830 eeepc_wmi_rfkill_exit(eeepc); 831 fail_rfkill: 832 eeepc_wmi_led_exit(eeepc); 833 fail_leds: 834 eeepc_wmi_input_exit(eeepc); 835 fail_input: 836 eeepc_wmi_platform_exit(eeepc); 837 fail_platform: 838 kfree(eeepc); 839 return ERR_PTR(err); 840 } 841 842 static int eeepc_wmi_remove(struct platform_device *device) 843 { 844 struct eeepc_wmi *eeepc; 845 846 eeepc = platform_get_drvdata(device); 847 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID); 848 eeepc_wmi_backlight_exit(eeepc); 849 eeepc_wmi_input_exit(eeepc); 850 eeepc_wmi_led_exit(eeepc); 851 eeepc_wmi_rfkill_exit(eeepc); 852 eeepc_wmi_debugfs_exit(eeepc); 853 eeepc_wmi_platform_exit(eeepc); 854 855 kfree(eeepc); 856 return 0; 857 } 858 859 static struct platform_driver platform_driver = { 860 .driver = { 861 .name = EEEPC_WMI_FILE, 862 .owner = THIS_MODULE, 863 }, 864 }; 865 866 static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level, 867 void *context, void **retval) 868 { 869 pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID); 870 *(bool *)context = true; 871 return AE_CTRL_TERMINATE; 872 } 873 874 static int __init eeepc_wmi_check_atkd(void) 875 { 876 acpi_status status; 877 bool found = false; 878 879 status = acpi_get_devices(EEEPC_ACPI_HID, eeepc_wmi_parse_device, 880 &found, NULL); 881 882 if (ACPI_FAILURE(status) || !found) 883 return 0; 884 return -1; 885 } 886 887 static int __init eeepc_wmi_init(void) 888 { 889 int err; 890 891 if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) || 892 !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) { 893 pr_warning("No known WMI GUID found\n"); 894 return -ENODEV; 895 } 896 897 if (eeepc_wmi_check_atkd()) { 898 pr_warning("WMI device present, but legacy ATKD device is also " 899 "present and enabled."); 900 pr_warning("You probably booted with acpi_osi=\"Linux\" or " 901 "acpi_osi=\"!Windows 2009\""); 902 pr_warning("Can't load eeepc-wmi, use default acpi_osi " 903 "(preferred) or eeepc-laptop"); 904 return -ENODEV; 905 } 906 907 platform_device = eeepc_wmi_add(); 908 if (IS_ERR(platform_device)) { 909 err = PTR_ERR(platform_device); 910 goto fail_eeepc_wmi; 911 } 912 913 err = platform_driver_register(&platform_driver); 914 if (err) { 915 pr_warning("Unable to register platform driver\n"); 916 goto fail_platform_driver; 917 } 918 919 return 0; 920 921 fail_platform_driver: 922 eeepc_wmi_remove(platform_device); 923 fail_eeepc_wmi: 924 return err; 925 } 926 927 static void __exit eeepc_wmi_exit(void) 928 { 929 eeepc_wmi_remove(platform_device); 930 platform_driver_unregister(&platform_driver); 931 } 932 933 module_init(eeepc_wmi_init); 934 module_exit(eeepc_wmi_exit); 935