1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Huawei WMI laptop extras driver 4 * 5 * Copyright (C) 2018 Ayman Bagabas <ayman.bagabas@gmail.com> 6 */ 7 8 #include <linux/acpi.h> 9 #include <linux/debugfs.h> 10 #include <linux/delay.h> 11 #include <linux/dmi.h> 12 #include <linux/input.h> 13 #include <linux/input/sparse-keymap.h> 14 #include <linux/leds.h> 15 #include <linux/module.h> 16 #include <linux/mutex.h> 17 #include <linux/platform_device.h> 18 #include <linux/power_supply.h> 19 #include <linux/sysfs.h> 20 #include <linux/wmi.h> 21 #include <acpi/battery.h> 22 23 /* 24 * Huawei WMI GUIDs 25 */ 26 #define HWMI_METHOD_GUID "ABBC0F5B-8EA1-11D1-A000-C90629100000" 27 #define HWMI_EVENT_GUID "ABBC0F5C-8EA1-11D1-A000-C90629100000" 28 29 /* Legacy GUIDs */ 30 #define WMI0_EXPENSIVE_GUID "39142400-C6A3-40fa-BADB-8A2652834100" 31 #define WMI0_EVENT_GUID "59142400-C6A3-40fa-BADB-8A2652834100" 32 33 /* HWMI commands */ 34 35 enum { 36 BATTERY_THRESH_GET = 0x00001103, /* \GBTT */ 37 BATTERY_THRESH_SET = 0x00001003, /* \SBTT */ 38 FN_LOCK_GET = 0x00000604, /* \GFRS */ 39 FN_LOCK_SET = 0x00000704, /* \SFRS */ 40 MICMUTE_LED_SET = 0x00000b04, /* \SMLS */ 41 }; 42 43 union hwmi_arg { 44 u64 cmd; 45 u8 args[8]; 46 }; 47 48 struct quirk_entry { 49 bool battery_reset; 50 bool ec_micmute; 51 bool report_brightness; 52 }; 53 54 static struct quirk_entry *quirks; 55 56 struct huawei_wmi_debug { 57 struct dentry *root; 58 u64 arg; 59 }; 60 61 struct huawei_wmi { 62 bool battery_available; 63 bool fn_lock_available; 64 65 struct huawei_wmi_debug debug; 66 struct led_classdev cdev; 67 struct device *dev; 68 69 struct mutex wmi_lock; 70 }; 71 72 static struct huawei_wmi *huawei_wmi; 73 74 static const struct key_entry huawei_wmi_keymap[] = { 75 { KE_KEY, 0x281, { KEY_BRIGHTNESSDOWN } }, 76 { KE_KEY, 0x282, { KEY_BRIGHTNESSUP } }, 77 { KE_KEY, 0x284, { KEY_MUTE } }, 78 { KE_KEY, 0x285, { KEY_VOLUMEDOWN } }, 79 { KE_KEY, 0x286, { KEY_VOLUMEUP } }, 80 { KE_KEY, 0x287, { KEY_MICMUTE } }, 81 { KE_KEY, 0x289, { KEY_WLAN } }, 82 // Huawei |M| key 83 { KE_KEY, 0x28a, { KEY_CONFIG } }, 84 // Keyboard backlit 85 { KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } }, 86 { KE_IGNORE, 0x294, { KEY_KBDILLUMUP } }, 87 { KE_IGNORE, 0x295, { KEY_KBDILLUMUP } }, 88 // Ignore Ambient Light Sensoring 89 { KE_KEY, 0x2c1, { KEY_RESERVED } }, 90 { KE_END, 0 } 91 }; 92 93 static int battery_reset = -1; 94 static int report_brightness = -1; 95 96 module_param(battery_reset, bint, 0444); 97 MODULE_PARM_DESC(battery_reset, 98 "Reset battery charge values to (0-0) before disabling it using (0-100)"); 99 module_param(report_brightness, bint, 0444); 100 MODULE_PARM_DESC(report_brightness, 101 "Report brightness keys."); 102 103 /* Quirks */ 104 105 static int __init dmi_matched(const struct dmi_system_id *dmi) 106 { 107 quirks = dmi->driver_data; 108 return 1; 109 } 110 111 static struct quirk_entry quirk_unknown = { 112 }; 113 114 static struct quirk_entry quirk_battery_reset = { 115 .battery_reset = true, 116 }; 117 118 static struct quirk_entry quirk_matebook_x = { 119 .ec_micmute = true, 120 .report_brightness = true, 121 }; 122 123 static const struct dmi_system_id huawei_quirks[] = { 124 { 125 .callback = dmi_matched, 126 .ident = "Huawei MACH-WX9", 127 .matches = { 128 DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"), 129 DMI_MATCH(DMI_PRODUCT_NAME, "MACH-WX9"), 130 }, 131 .driver_data = &quirk_battery_reset 132 }, 133 { 134 .callback = dmi_matched, 135 .ident = "Huawei MateBook X", 136 .matches = { 137 DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"), 138 DMI_MATCH(DMI_PRODUCT_NAME, "HUAWEI MateBook X") 139 }, 140 .driver_data = &quirk_matebook_x 141 }, 142 { } 143 }; 144 145 /* Utils */ 146 147 static int huawei_wmi_call(struct huawei_wmi *huawei, 148 struct acpi_buffer *in, struct acpi_buffer *out) 149 { 150 acpi_status status; 151 152 mutex_lock(&huawei->wmi_lock); 153 status = wmi_evaluate_method(HWMI_METHOD_GUID, 0, 1, in, out); 154 mutex_unlock(&huawei->wmi_lock); 155 if (ACPI_FAILURE(status)) { 156 dev_err(huawei->dev, "Failed to evaluate wmi method\n"); 157 return -ENODEV; 158 } 159 160 return 0; 161 } 162 163 /* HWMI takes a 64 bit input and returns either a package with 2 buffers, one of 164 * 4 bytes and the other of 256 bytes, or one buffer of size 0x104 (260) bytes. 165 * The first 4 bytes are ignored, we ignore the first 4 bytes buffer if we got a 166 * package, or skip the first 4 if a buffer of 0x104 is used. The first byte of 167 * the remaining 0x100 sized buffer has the return status of every call. In case 168 * the return status is non-zero, we return -ENODEV but still copy the returned 169 * buffer to the given buffer parameter (buf). 170 */ 171 static int huawei_wmi_cmd(u64 arg, u8 *buf, size_t buflen) 172 { 173 struct huawei_wmi *huawei = huawei_wmi; 174 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 175 struct acpi_buffer in; 176 union acpi_object *obj; 177 size_t len; 178 int err, i; 179 180 in.length = sizeof(arg); 181 in.pointer = &arg; 182 183 /* Some models require calling HWMI twice to execute a command. We evaluate 184 * HWMI and if we get a non-zero return status we evaluate it again. 185 */ 186 for (i = 0; i < 2; i++) { 187 err = huawei_wmi_call(huawei, &in, &out); 188 if (err) 189 goto fail_cmd; 190 191 obj = out.pointer; 192 if (!obj) { 193 err = -EIO; 194 goto fail_cmd; 195 } 196 197 switch (obj->type) { 198 /* Models that implement both "legacy" and HWMI tend to return a 0x104 199 * sized buffer instead of a package of 0x4 and 0x100 buffers. 200 */ 201 case ACPI_TYPE_BUFFER: 202 if (obj->buffer.length == 0x104) { 203 // Skip the first 4 bytes. 204 obj->buffer.pointer += 4; 205 len = 0x100; 206 } else { 207 dev_err(huawei->dev, "Bad buffer length, got %d\n", obj->buffer.length); 208 err = -EIO; 209 goto fail_cmd; 210 } 211 212 break; 213 /* HWMI returns a package with 2 buffer elements, one of 4 bytes and the 214 * other is 256 bytes. 215 */ 216 case ACPI_TYPE_PACKAGE: 217 if (obj->package.count != 2) { 218 dev_err(huawei->dev, "Bad package count, got %d\n", obj->package.count); 219 err = -EIO; 220 goto fail_cmd; 221 } 222 223 obj = &obj->package.elements[1]; 224 if (obj->type != ACPI_TYPE_BUFFER) { 225 dev_err(huawei->dev, "Bad package element type, got %d\n", obj->type); 226 err = -EIO; 227 goto fail_cmd; 228 } 229 len = obj->buffer.length; 230 231 break; 232 /* Shouldn't get here! */ 233 default: 234 dev_err(huawei->dev, "Unexpected obj type, got: %d\n", obj->type); 235 err = -EIO; 236 goto fail_cmd; 237 } 238 239 if (!*obj->buffer.pointer) 240 break; 241 } 242 243 err = (*obj->buffer.pointer) ? -ENODEV : 0; 244 245 if (buf) { 246 len = min(buflen, len); 247 memcpy(buf, obj->buffer.pointer, len); 248 } 249 250 fail_cmd: 251 kfree(out.pointer); 252 return err; 253 } 254 255 /* LEDs */ 256 257 static int huawei_wmi_micmute_led_set(struct led_classdev *led_cdev, 258 enum led_brightness brightness) 259 { 260 /* This is a workaround until the "legacy" interface is implemented. */ 261 if (quirks && quirks->ec_micmute) { 262 char *acpi_method; 263 acpi_handle handle; 264 acpi_status status; 265 union acpi_object args[3]; 266 struct acpi_object_list arg_list = { 267 .pointer = args, 268 .count = ARRAY_SIZE(args), 269 }; 270 271 handle = ec_get_handle(); 272 if (!handle) 273 return -ENODEV; 274 275 args[0].type = args[1].type = args[2].type = ACPI_TYPE_INTEGER; 276 args[1].integer.value = 0x04; 277 278 if (acpi_has_method(handle, "SPIN")) { 279 acpi_method = "SPIN"; 280 args[0].integer.value = 0; 281 args[2].integer.value = brightness ? 1 : 0; 282 } else if (acpi_has_method(handle, "WPIN")) { 283 acpi_method = "WPIN"; 284 args[0].integer.value = 1; 285 args[2].integer.value = brightness ? 0 : 1; 286 } else { 287 return -ENODEV; 288 } 289 290 status = acpi_evaluate_object(handle, acpi_method, &arg_list, NULL); 291 if (ACPI_FAILURE(status)) 292 return -ENODEV; 293 294 return 0; 295 } else { 296 union hwmi_arg arg; 297 298 arg.cmd = MICMUTE_LED_SET; 299 arg.args[2] = brightness; 300 301 return huawei_wmi_cmd(arg.cmd, NULL, 0); 302 } 303 } 304 305 static void huawei_wmi_leds_setup(struct device *dev) 306 { 307 struct huawei_wmi *huawei = dev_get_drvdata(dev); 308 309 huawei->cdev.name = "platform::micmute"; 310 huawei->cdev.max_brightness = 1; 311 huawei->cdev.brightness_set_blocking = &huawei_wmi_micmute_led_set; 312 huawei->cdev.default_trigger = "audio-micmute"; 313 huawei->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE); 314 huawei->cdev.dev = dev; 315 huawei->cdev.flags = LED_CORE_SUSPENDRESUME; 316 317 devm_led_classdev_register(dev, &huawei->cdev); 318 } 319 320 /* Battery protection */ 321 322 static int huawei_wmi_battery_get(int *start, int *end) 323 { 324 u8 ret[0x100]; 325 int err, i; 326 327 err = huawei_wmi_cmd(BATTERY_THRESH_GET, ret, sizeof(ret)); 328 if (err) 329 return err; 330 331 /* Find the last two non-zero values. Return status is ignored. */ 332 i = ARRAY_SIZE(ret) - 1; 333 do { 334 if (start) 335 *start = ret[i-1]; 336 if (end) 337 *end = ret[i]; 338 } while (i > 2 && !ret[i--]); 339 340 return 0; 341 } 342 343 static int huawei_wmi_battery_set(int start, int end) 344 { 345 union hwmi_arg arg; 346 int err; 347 348 if (start < 0 || end < 0 || start > 100 || end > 100) 349 return -EINVAL; 350 351 arg.cmd = BATTERY_THRESH_SET; 352 arg.args[2] = start; 353 arg.args[3] = end; 354 355 /* This is an edge case were some models turn battery protection 356 * off without changing their thresholds values. We clear the 357 * values before turning off protection. Sometimes we need a sleep delay to 358 * make sure these values make their way to EC memory. 359 */ 360 if (quirks && quirks->battery_reset && start == 0 && end == 100) { 361 err = huawei_wmi_battery_set(0, 0); 362 if (err) 363 return err; 364 365 msleep(1000); 366 } 367 368 err = huawei_wmi_cmd(arg.cmd, NULL, 0); 369 370 return err; 371 } 372 373 static ssize_t charge_control_start_threshold_show(struct device *dev, 374 struct device_attribute *attr, 375 char *buf) 376 { 377 int err, start; 378 379 err = huawei_wmi_battery_get(&start, NULL); 380 if (err) 381 return err; 382 383 return sprintf(buf, "%d\n", start); 384 } 385 386 static ssize_t charge_control_end_threshold_show(struct device *dev, 387 struct device_attribute *attr, 388 char *buf) 389 { 390 int err, end; 391 392 err = huawei_wmi_battery_get(NULL, &end); 393 if (err) 394 return err; 395 396 return sprintf(buf, "%d\n", end); 397 } 398 399 static ssize_t charge_control_thresholds_show(struct device *dev, 400 struct device_attribute *attr, 401 char *buf) 402 { 403 int err, start, end; 404 405 err = huawei_wmi_battery_get(&start, &end); 406 if (err) 407 return err; 408 409 return sprintf(buf, "%d %d\n", start, end); 410 } 411 412 static ssize_t charge_control_start_threshold_store(struct device *dev, 413 struct device_attribute *attr, 414 const char *buf, size_t size) 415 { 416 int err, start, end; 417 418 err = huawei_wmi_battery_get(NULL, &end); 419 if (err) 420 return err; 421 422 if (sscanf(buf, "%d", &start) != 1) 423 return -EINVAL; 424 425 err = huawei_wmi_battery_set(start, end); 426 if (err) 427 return err; 428 429 return size; 430 } 431 432 static ssize_t charge_control_end_threshold_store(struct device *dev, 433 struct device_attribute *attr, 434 const char *buf, size_t size) 435 { 436 int err, start, end; 437 438 err = huawei_wmi_battery_get(&start, NULL); 439 if (err) 440 return err; 441 442 if (sscanf(buf, "%d", &end) != 1) 443 return -EINVAL; 444 445 err = huawei_wmi_battery_set(start, end); 446 if (err) 447 return err; 448 449 return size; 450 } 451 452 static ssize_t charge_control_thresholds_store(struct device *dev, 453 struct device_attribute *attr, 454 const char *buf, size_t size) 455 { 456 int err, start, end; 457 458 if (sscanf(buf, "%d %d", &start, &end) != 2) 459 return -EINVAL; 460 461 err = huawei_wmi_battery_set(start, end); 462 if (err) 463 return err; 464 465 return size; 466 } 467 468 static DEVICE_ATTR_RW(charge_control_start_threshold); 469 static DEVICE_ATTR_RW(charge_control_end_threshold); 470 static DEVICE_ATTR_RW(charge_control_thresholds); 471 472 static int huawei_wmi_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook) 473 { 474 int err = 0; 475 476 err = device_create_file(&battery->dev, &dev_attr_charge_control_start_threshold); 477 if (err) 478 return err; 479 480 err = device_create_file(&battery->dev, &dev_attr_charge_control_end_threshold); 481 if (err) 482 device_remove_file(&battery->dev, &dev_attr_charge_control_start_threshold); 483 484 return err; 485 } 486 487 static int huawei_wmi_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook) 488 { 489 device_remove_file(&battery->dev, &dev_attr_charge_control_start_threshold); 490 device_remove_file(&battery->dev, &dev_attr_charge_control_end_threshold); 491 492 return 0; 493 } 494 495 static struct acpi_battery_hook huawei_wmi_battery_hook = { 496 .add_battery = huawei_wmi_battery_add, 497 .remove_battery = huawei_wmi_battery_remove, 498 .name = "Huawei Battery Extension" 499 }; 500 501 static void huawei_wmi_battery_setup(struct device *dev) 502 { 503 struct huawei_wmi *huawei = dev_get_drvdata(dev); 504 505 huawei->battery_available = true; 506 if (huawei_wmi_battery_get(NULL, NULL)) { 507 huawei->battery_available = false; 508 return; 509 } 510 511 battery_hook_register(&huawei_wmi_battery_hook); 512 device_create_file(dev, &dev_attr_charge_control_thresholds); 513 } 514 515 static void huawei_wmi_battery_exit(struct device *dev) 516 { 517 struct huawei_wmi *huawei = dev_get_drvdata(dev); 518 519 if (huawei->battery_available) { 520 battery_hook_unregister(&huawei_wmi_battery_hook); 521 device_remove_file(dev, &dev_attr_charge_control_thresholds); 522 } 523 } 524 525 /* Fn lock */ 526 527 static int huawei_wmi_fn_lock_get(int *on) 528 { 529 u8 ret[0x100] = { 0 }; 530 int err, i; 531 532 err = huawei_wmi_cmd(FN_LOCK_GET, ret, 0x100); 533 if (err) 534 return err; 535 536 /* Find the first non-zero value. Return status is ignored. */ 537 i = 1; 538 do { 539 if (on) 540 *on = ret[i] - 1; // -1 undefined, 0 off, 1 on. 541 } while (i < 0xff && !ret[i++]); 542 543 return 0; 544 } 545 546 static int huawei_wmi_fn_lock_set(int on) 547 { 548 union hwmi_arg arg; 549 550 arg.cmd = FN_LOCK_SET; 551 arg.args[2] = on + 1; // 0 undefined, 1 off, 2 on. 552 553 return huawei_wmi_cmd(arg.cmd, NULL, 0); 554 } 555 556 static ssize_t fn_lock_state_show(struct device *dev, 557 struct device_attribute *attr, 558 char *buf) 559 { 560 int err, on; 561 562 err = huawei_wmi_fn_lock_get(&on); 563 if (err) 564 return err; 565 566 return sprintf(buf, "%d\n", on); 567 } 568 569 static ssize_t fn_lock_state_store(struct device *dev, 570 struct device_attribute *attr, 571 const char *buf, size_t size) 572 { 573 int on, err; 574 575 if (kstrtoint(buf, 10, &on) || 576 on < 0 || on > 1) 577 return -EINVAL; 578 579 err = huawei_wmi_fn_lock_set(on); 580 if (err) 581 return err; 582 583 return size; 584 } 585 586 static DEVICE_ATTR_RW(fn_lock_state); 587 588 static void huawei_wmi_fn_lock_setup(struct device *dev) 589 { 590 struct huawei_wmi *huawei = dev_get_drvdata(dev); 591 592 huawei->fn_lock_available = true; 593 if (huawei_wmi_fn_lock_get(NULL)) { 594 huawei->fn_lock_available = false; 595 return; 596 } 597 598 device_create_file(dev, &dev_attr_fn_lock_state); 599 } 600 601 static void huawei_wmi_fn_lock_exit(struct device *dev) 602 { 603 struct huawei_wmi *huawei = dev_get_drvdata(dev); 604 605 if (huawei->fn_lock_available) 606 device_remove_file(dev, &dev_attr_fn_lock_state); 607 } 608 609 /* debugfs */ 610 611 static void huawei_wmi_debugfs_call_dump(struct seq_file *m, void *data, 612 union acpi_object *obj) 613 { 614 struct huawei_wmi *huawei = m->private; 615 int i; 616 617 switch (obj->type) { 618 case ACPI_TYPE_INTEGER: 619 seq_printf(m, "0x%llx", obj->integer.value); 620 break; 621 case ACPI_TYPE_STRING: 622 seq_printf(m, "\"%.*s\"", obj->string.length, obj->string.pointer); 623 break; 624 case ACPI_TYPE_BUFFER: 625 seq_puts(m, "{"); 626 for (i = 0; i < obj->buffer.length; i++) { 627 seq_printf(m, "0x%02x", obj->buffer.pointer[i]); 628 if (i < obj->buffer.length - 1) 629 seq_puts(m, ","); 630 } 631 seq_puts(m, "}"); 632 break; 633 case ACPI_TYPE_PACKAGE: 634 seq_puts(m, "["); 635 for (i = 0; i < obj->package.count; i++) { 636 huawei_wmi_debugfs_call_dump(m, huawei, &obj->package.elements[i]); 637 if (i < obj->package.count - 1) 638 seq_puts(m, ","); 639 } 640 seq_puts(m, "]"); 641 break; 642 default: 643 dev_err(huawei->dev, "Unexpected obj type, got %d\n", obj->type); 644 return; 645 } 646 } 647 648 static int huawei_wmi_debugfs_call_show(struct seq_file *m, void *data) 649 { 650 struct huawei_wmi *huawei = m->private; 651 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 652 struct acpi_buffer in; 653 union acpi_object *obj; 654 int err; 655 656 in.length = sizeof(u64); 657 in.pointer = &huawei->debug.arg; 658 659 err = huawei_wmi_call(huawei, &in, &out); 660 if (err) 661 return err; 662 663 obj = out.pointer; 664 if (!obj) { 665 err = -EIO; 666 goto fail_debugfs_call; 667 } 668 669 huawei_wmi_debugfs_call_dump(m, huawei, obj); 670 671 fail_debugfs_call: 672 kfree(out.pointer); 673 return err; 674 } 675 676 DEFINE_SHOW_ATTRIBUTE(huawei_wmi_debugfs_call); 677 678 static void huawei_wmi_debugfs_setup(struct device *dev) 679 { 680 struct huawei_wmi *huawei = dev_get_drvdata(dev); 681 682 huawei->debug.root = debugfs_create_dir("huawei-wmi", NULL); 683 684 debugfs_create_x64("arg", 0644, huawei->debug.root, 685 &huawei->debug.arg); 686 debugfs_create_file("call", 0400, 687 huawei->debug.root, huawei, &huawei_wmi_debugfs_call_fops); 688 } 689 690 static void huawei_wmi_debugfs_exit(struct device *dev) 691 { 692 struct huawei_wmi *huawei = dev_get_drvdata(dev); 693 694 debugfs_remove_recursive(huawei->debug.root); 695 } 696 697 /* Input */ 698 699 static void huawei_wmi_process_key(struct input_dev *idev, int code) 700 { 701 const struct key_entry *key; 702 703 /* 704 * WMI0 uses code 0x80 to indicate a hotkey event. 705 * The actual key is fetched from the method WQ00 706 * using WMI0_EXPENSIVE_GUID. 707 */ 708 if (code == 0x80) { 709 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 710 union acpi_object *obj; 711 acpi_status status; 712 713 status = wmi_query_block(WMI0_EXPENSIVE_GUID, 0, &response); 714 if (ACPI_FAILURE(status)) 715 return; 716 717 obj = (union acpi_object *)response.pointer; 718 if (obj && obj->type == ACPI_TYPE_INTEGER) 719 code = obj->integer.value; 720 721 kfree(response.pointer); 722 } 723 724 key = sparse_keymap_entry_from_scancode(idev, code); 725 if (!key) { 726 dev_info(&idev->dev, "Unknown key pressed, code: 0x%04x\n", code); 727 return; 728 } 729 730 if (quirks && !quirks->report_brightness && 731 (key->sw.code == KEY_BRIGHTNESSDOWN || 732 key->sw.code == KEY_BRIGHTNESSUP)) 733 return; 734 735 sparse_keymap_report_entry(idev, key, 1, true); 736 } 737 738 static void huawei_wmi_input_notify(u32 value, void *context) 739 { 740 struct input_dev *idev = (struct input_dev *)context; 741 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 742 union acpi_object *obj; 743 acpi_status status; 744 745 status = wmi_get_event_data(value, &response); 746 if (ACPI_FAILURE(status)) { 747 dev_err(&idev->dev, "Unable to get event data\n"); 748 return; 749 } 750 751 obj = (union acpi_object *)response.pointer; 752 if (obj && obj->type == ACPI_TYPE_INTEGER) 753 huawei_wmi_process_key(idev, obj->integer.value); 754 else 755 dev_err(&idev->dev, "Bad response type\n"); 756 757 kfree(response.pointer); 758 } 759 760 static int huawei_wmi_input_setup(struct device *dev, const char *guid) 761 { 762 struct input_dev *idev; 763 acpi_status status; 764 int err; 765 766 idev = devm_input_allocate_device(dev); 767 if (!idev) 768 return -ENOMEM; 769 770 idev->name = "Huawei WMI hotkeys"; 771 idev->phys = "wmi/input0"; 772 idev->id.bustype = BUS_HOST; 773 idev->dev.parent = dev; 774 775 err = sparse_keymap_setup(idev, huawei_wmi_keymap, NULL); 776 if (err) 777 return err; 778 779 err = input_register_device(idev); 780 if (err) 781 return err; 782 783 status = wmi_install_notify_handler(guid, huawei_wmi_input_notify, idev); 784 if (ACPI_FAILURE(status)) 785 return -EIO; 786 787 return 0; 788 } 789 790 static void huawei_wmi_input_exit(struct device *dev, const char *guid) 791 { 792 wmi_remove_notify_handler(guid); 793 } 794 795 /* Huawei driver */ 796 797 static const struct wmi_device_id huawei_wmi_events_id_table[] = { 798 { .guid_string = WMI0_EVENT_GUID }, 799 { .guid_string = HWMI_EVENT_GUID }, 800 { } 801 }; 802 803 static int huawei_wmi_probe(struct platform_device *pdev) 804 { 805 const struct wmi_device_id *guid = huawei_wmi_events_id_table; 806 int err; 807 808 platform_set_drvdata(pdev, huawei_wmi); 809 huawei_wmi->dev = &pdev->dev; 810 811 while (*guid->guid_string) { 812 if (wmi_has_guid(guid->guid_string)) { 813 err = huawei_wmi_input_setup(&pdev->dev, guid->guid_string); 814 if (err) { 815 dev_err(&pdev->dev, "Failed to setup input on %s\n", guid->guid_string); 816 return err; 817 } 818 } 819 820 guid++; 821 } 822 823 if (wmi_has_guid(HWMI_METHOD_GUID)) { 824 mutex_init(&huawei_wmi->wmi_lock); 825 826 huawei_wmi_leds_setup(&pdev->dev); 827 huawei_wmi_fn_lock_setup(&pdev->dev); 828 huawei_wmi_battery_setup(&pdev->dev); 829 huawei_wmi_debugfs_setup(&pdev->dev); 830 } 831 832 return 0; 833 } 834 835 static void huawei_wmi_remove(struct platform_device *pdev) 836 { 837 const struct wmi_device_id *guid = huawei_wmi_events_id_table; 838 839 while (*guid->guid_string) { 840 if (wmi_has_guid(guid->guid_string)) 841 huawei_wmi_input_exit(&pdev->dev, guid->guid_string); 842 843 guid++; 844 } 845 846 if (wmi_has_guid(HWMI_METHOD_GUID)) { 847 huawei_wmi_debugfs_exit(&pdev->dev); 848 huawei_wmi_battery_exit(&pdev->dev); 849 huawei_wmi_fn_lock_exit(&pdev->dev); 850 } 851 } 852 853 static struct platform_driver huawei_wmi_driver = { 854 .driver = { 855 .name = "huawei-wmi", 856 }, 857 .probe = huawei_wmi_probe, 858 .remove_new = huawei_wmi_remove, 859 }; 860 861 static __init int huawei_wmi_init(void) 862 { 863 struct platform_device *pdev; 864 int err; 865 866 huawei_wmi = kzalloc(sizeof(struct huawei_wmi), GFP_KERNEL); 867 if (!huawei_wmi) 868 return -ENOMEM; 869 870 quirks = &quirk_unknown; 871 dmi_check_system(huawei_quirks); 872 if (battery_reset != -1) 873 quirks->battery_reset = battery_reset; 874 if (report_brightness != -1) 875 quirks->report_brightness = report_brightness; 876 877 err = platform_driver_register(&huawei_wmi_driver); 878 if (err) 879 goto pdrv_err; 880 881 pdev = platform_device_register_simple("huawei-wmi", PLATFORM_DEVID_NONE, NULL, 0); 882 if (IS_ERR(pdev)) { 883 err = PTR_ERR(pdev); 884 goto pdev_err; 885 } 886 887 return 0; 888 889 pdev_err: 890 platform_driver_unregister(&huawei_wmi_driver); 891 pdrv_err: 892 kfree(huawei_wmi); 893 return err; 894 } 895 896 static __exit void huawei_wmi_exit(void) 897 { 898 struct platform_device *pdev = to_platform_device(huawei_wmi->dev); 899 900 platform_device_unregister(pdev); 901 platform_driver_unregister(&huawei_wmi_driver); 902 903 kfree(huawei_wmi); 904 } 905 906 module_init(huawei_wmi_init); 907 module_exit(huawei_wmi_exit); 908 909 MODULE_ALIAS("wmi:"HWMI_METHOD_GUID); 910 MODULE_DEVICE_TABLE(wmi, huawei_wmi_events_id_table); 911 MODULE_AUTHOR("Ayman Bagabas <ayman.bagabas@gmail.com>"); 912 MODULE_DESCRIPTION("Huawei WMI laptop extras driver"); 913 MODULE_LICENSE("GPL v2"); 914