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