0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "ACPI: button: " fmt
0010
0011 #include <linux/compiler.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/init.h>
0015 #include <linux/types.h>
0016 #include <linux/proc_fs.h>
0017 #include <linux/seq_file.h>
0018 #include <linux/input.h>
0019 #include <linux/slab.h>
0020 #include <linux/acpi.h>
0021 #include <linux/dmi.h>
0022 #include <acpi/button.h>
0023
0024 #define ACPI_BUTTON_CLASS "button"
0025 #define ACPI_BUTTON_FILE_STATE "state"
0026 #define ACPI_BUTTON_TYPE_UNKNOWN 0x00
0027 #define ACPI_BUTTON_NOTIFY_STATUS 0x80
0028
0029 #define ACPI_BUTTON_SUBCLASS_POWER "power"
0030 #define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
0031 #define ACPI_BUTTON_TYPE_POWER 0x01
0032
0033 #define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
0034 #define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
0035 #define ACPI_BUTTON_TYPE_SLEEP 0x03
0036
0037 #define ACPI_BUTTON_SUBCLASS_LID "lid"
0038 #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
0039 #define ACPI_BUTTON_TYPE_LID 0x05
0040
0041 enum {
0042 ACPI_BUTTON_LID_INIT_IGNORE,
0043 ACPI_BUTTON_LID_INIT_OPEN,
0044 ACPI_BUTTON_LID_INIT_METHOD,
0045 ACPI_BUTTON_LID_INIT_DISABLED,
0046 };
0047
0048 static const char * const lid_init_state_str[] = {
0049 [ACPI_BUTTON_LID_INIT_IGNORE] = "ignore",
0050 [ACPI_BUTTON_LID_INIT_OPEN] = "open",
0051 [ACPI_BUTTON_LID_INIT_METHOD] = "method",
0052 [ACPI_BUTTON_LID_INIT_DISABLED] = "disabled",
0053 };
0054
0055 MODULE_AUTHOR("Paul Diefenbaugh");
0056 MODULE_DESCRIPTION("ACPI Button Driver");
0057 MODULE_LICENSE("GPL");
0058
0059 static const struct acpi_device_id button_device_ids[] = {
0060 {ACPI_BUTTON_HID_LID, 0},
0061 {ACPI_BUTTON_HID_SLEEP, 0},
0062 {ACPI_BUTTON_HID_SLEEPF, 0},
0063 {ACPI_BUTTON_HID_POWER, 0},
0064 {ACPI_BUTTON_HID_POWERF, 0},
0065 {"", 0},
0066 };
0067 MODULE_DEVICE_TABLE(acpi, button_device_ids);
0068
0069
0070 static const struct dmi_system_id dmi_lid_quirks[] = {
0071 {
0072
0073 .matches = {
0074 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
0075 DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
0076 DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
0077 },
0078 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
0079 },
0080 {
0081
0082
0083
0084
0085 .matches = {
0086 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
0087 DMI_MATCH(DMI_PRODUCT_NAME, "82BG"),
0088 },
0089 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
0090 },
0091 {
0092
0093
0094
0095
0096 .matches = {
0097 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
0098 DMI_MATCH(DMI_PRODUCT_NAME, "E2215T"),
0099 },
0100 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
0101 },
0102 {
0103
0104
0105
0106
0107 .matches = {
0108 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
0109 DMI_MATCH(DMI_PRODUCT_NAME, "E2228T"),
0110 },
0111 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
0112 },
0113 {
0114
0115
0116
0117
0118 .matches = {
0119 DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
0120 DMI_MATCH(DMI_PRODUCT_NAME, "Razer Blade Stealth 13 Late 2019"),
0121 },
0122 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
0123 },
0124 {}
0125 };
0126
0127 static int acpi_button_add(struct acpi_device *device);
0128 static int acpi_button_remove(struct acpi_device *device);
0129 static void acpi_button_notify(struct acpi_device *device, u32 event);
0130
0131 #ifdef CONFIG_PM_SLEEP
0132 static int acpi_button_suspend(struct device *dev);
0133 static int acpi_button_resume(struct device *dev);
0134 #else
0135 #define acpi_button_suspend NULL
0136 #define acpi_button_resume NULL
0137 #endif
0138 static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
0139
0140 static struct acpi_driver acpi_button_driver = {
0141 .name = "button",
0142 .class = ACPI_BUTTON_CLASS,
0143 .ids = button_device_ids,
0144 .ops = {
0145 .add = acpi_button_add,
0146 .remove = acpi_button_remove,
0147 .notify = acpi_button_notify,
0148 },
0149 .drv.pm = &acpi_button_pm,
0150 };
0151
0152 struct acpi_button {
0153 unsigned int type;
0154 struct input_dev *input;
0155 char phys[32];
0156 unsigned long pushed;
0157 int last_state;
0158 ktime_t last_time;
0159 bool suspended;
0160 bool lid_state_initialized;
0161 };
0162
0163 static struct acpi_device *lid_device;
0164 static long lid_init_state = -1;
0165
0166 static unsigned long lid_report_interval __read_mostly = 500;
0167 module_param(lid_report_interval, ulong, 0644);
0168 MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
0169
0170
0171 static struct proc_dir_entry *acpi_button_dir;
0172 static struct proc_dir_entry *acpi_lid_dir;
0173
0174 static int acpi_lid_evaluate_state(struct acpi_device *device)
0175 {
0176 unsigned long long lid_state;
0177 acpi_status status;
0178
0179 status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
0180 if (ACPI_FAILURE(status))
0181 return -ENODEV;
0182
0183 return lid_state ? 1 : 0;
0184 }
0185
0186 static int acpi_lid_notify_state(struct acpi_device *device, int state)
0187 {
0188 struct acpi_button *button = acpi_driver_data(device);
0189 ktime_t next_report;
0190 bool do_update;
0191
0192
0193
0194
0195
0196
0197
0198
0199 if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE ||
0200 button->last_state != !!state)
0201 do_update = true;
0202 else
0203 do_update = false;
0204
0205 next_report = ktime_add(button->last_time,
0206 ms_to_ktime(lid_report_interval));
0207 if (button->last_state == !!state &&
0208 ktime_after(ktime_get(), next_report)) {
0209
0210 pr_warn_once("The lid device is not compliant to SW_LID.\n");
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
0239 do_update = true;
0240
0241
0242
0243
0244
0245
0246
0247
0248 if (!state) {
0249 input_report_switch(button->input,
0250 SW_LID, state);
0251 input_sync(button->input);
0252 }
0253 }
0254 }
0255
0256 if (do_update) {
0257 acpi_handle_debug(device->handle, "ACPI LID %s\n",
0258 state ? "open" : "closed");
0259 input_report_switch(button->input, SW_LID, !state);
0260 input_sync(button->input);
0261 button->last_state = !!state;
0262 button->last_time = ktime_get();
0263 }
0264
0265 return 0;
0266 }
0267
0268 static int __maybe_unused acpi_button_state_seq_show(struct seq_file *seq,
0269 void *offset)
0270 {
0271 struct acpi_device *device = seq->private;
0272 int state;
0273
0274 state = acpi_lid_evaluate_state(device);
0275 seq_printf(seq, "state: %s\n",
0276 state < 0 ? "unsupported" : (state ? "open" : "closed"));
0277 return 0;
0278 }
0279
0280 static int acpi_button_add_fs(struct acpi_device *device)
0281 {
0282 struct acpi_button *button = acpi_driver_data(device);
0283 struct proc_dir_entry *entry = NULL;
0284 int ret = 0;
0285
0286
0287 if (button->type != ACPI_BUTTON_TYPE_LID)
0288 return 0;
0289
0290 if (acpi_button_dir || acpi_lid_dir) {
0291 pr_info("More than one Lid device found!\n");
0292 return -EEXIST;
0293 }
0294
0295
0296 acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
0297 if (!acpi_button_dir)
0298 return -ENODEV;
0299
0300
0301 acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
0302 if (!acpi_lid_dir) {
0303 ret = -ENODEV;
0304 goto remove_button_dir;
0305 }
0306
0307
0308 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
0309 if (!acpi_device_dir(device)) {
0310 ret = -ENODEV;
0311 goto remove_lid_dir;
0312 }
0313
0314
0315 entry = proc_create_single_data(ACPI_BUTTON_FILE_STATE, S_IRUGO,
0316 acpi_device_dir(device), acpi_button_state_seq_show,
0317 device);
0318 if (!entry) {
0319 ret = -ENODEV;
0320 goto remove_dev_dir;
0321 }
0322
0323 done:
0324 return ret;
0325
0326 remove_dev_dir:
0327 remove_proc_entry(acpi_device_bid(device),
0328 acpi_lid_dir);
0329 acpi_device_dir(device) = NULL;
0330 remove_lid_dir:
0331 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
0332 acpi_lid_dir = NULL;
0333 remove_button_dir:
0334 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
0335 acpi_button_dir = NULL;
0336 goto done;
0337 }
0338
0339 static int acpi_button_remove_fs(struct acpi_device *device)
0340 {
0341 struct acpi_button *button = acpi_driver_data(device);
0342
0343 if (button->type != ACPI_BUTTON_TYPE_LID)
0344 return 0;
0345
0346 remove_proc_entry(ACPI_BUTTON_FILE_STATE,
0347 acpi_device_dir(device));
0348 remove_proc_entry(acpi_device_bid(device),
0349 acpi_lid_dir);
0350 acpi_device_dir(device) = NULL;
0351 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
0352 acpi_lid_dir = NULL;
0353 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
0354 acpi_button_dir = NULL;
0355
0356 return 0;
0357 }
0358
0359
0360 int acpi_lid_open(void)
0361 {
0362 if (!lid_device)
0363 return -ENODEV;
0364
0365 return acpi_lid_evaluate_state(lid_device);
0366 }
0367 EXPORT_SYMBOL(acpi_lid_open);
0368
0369 static int acpi_lid_update_state(struct acpi_device *device,
0370 bool signal_wakeup)
0371 {
0372 int state;
0373
0374 state = acpi_lid_evaluate_state(device);
0375 if (state < 0)
0376 return state;
0377
0378 if (state && signal_wakeup)
0379 acpi_pm_wakeup_event(&device->dev);
0380
0381 return acpi_lid_notify_state(device, state);
0382 }
0383
0384 static void acpi_lid_initialize_state(struct acpi_device *device)
0385 {
0386 struct acpi_button *button = acpi_driver_data(device);
0387
0388 switch (lid_init_state) {
0389 case ACPI_BUTTON_LID_INIT_OPEN:
0390 (void)acpi_lid_notify_state(device, 1);
0391 break;
0392 case ACPI_BUTTON_LID_INIT_METHOD:
0393 (void)acpi_lid_update_state(device, false);
0394 break;
0395 case ACPI_BUTTON_LID_INIT_IGNORE:
0396 default:
0397 break;
0398 }
0399
0400 button->lid_state_initialized = true;
0401 }
0402
0403 static void acpi_button_notify(struct acpi_device *device, u32 event)
0404 {
0405 struct acpi_button *button = acpi_driver_data(device);
0406 struct input_dev *input;
0407
0408 switch (event) {
0409 case ACPI_FIXED_HARDWARE_EVENT:
0410 event = ACPI_BUTTON_NOTIFY_STATUS;
0411 fallthrough;
0412 case ACPI_BUTTON_NOTIFY_STATUS:
0413 input = button->input;
0414 if (button->type == ACPI_BUTTON_TYPE_LID) {
0415 if (button->lid_state_initialized)
0416 acpi_lid_update_state(device, true);
0417 } else {
0418 int keycode;
0419
0420 acpi_pm_wakeup_event(&device->dev);
0421 if (button->suspended)
0422 break;
0423
0424 keycode = test_bit(KEY_SLEEP, input->keybit) ?
0425 KEY_SLEEP : KEY_POWER;
0426 input_report_key(input, keycode, 1);
0427 input_sync(input);
0428 input_report_key(input, keycode, 0);
0429 input_sync(input);
0430
0431 acpi_bus_generate_netlink_event(
0432 device->pnp.device_class,
0433 dev_name(&device->dev),
0434 event, ++button->pushed);
0435 }
0436 break;
0437 default:
0438 acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
0439 event);
0440 break;
0441 }
0442 }
0443
0444 #ifdef CONFIG_PM_SLEEP
0445 static int acpi_button_suspend(struct device *dev)
0446 {
0447 struct acpi_device *device = to_acpi_device(dev);
0448 struct acpi_button *button = acpi_driver_data(device);
0449
0450 button->suspended = true;
0451 return 0;
0452 }
0453
0454 static int acpi_button_resume(struct device *dev)
0455 {
0456 struct acpi_device *device = to_acpi_device(dev);
0457 struct acpi_button *button = acpi_driver_data(device);
0458
0459 button->suspended = false;
0460 if (button->type == ACPI_BUTTON_TYPE_LID) {
0461 button->last_state = !!acpi_lid_evaluate_state(device);
0462 button->last_time = ktime_get();
0463 acpi_lid_initialize_state(device);
0464 }
0465 return 0;
0466 }
0467 #endif
0468
0469 static int acpi_lid_input_open(struct input_dev *input)
0470 {
0471 struct acpi_device *device = input_get_drvdata(input);
0472 struct acpi_button *button = acpi_driver_data(device);
0473
0474 button->last_state = !!acpi_lid_evaluate_state(device);
0475 button->last_time = ktime_get();
0476 acpi_lid_initialize_state(device);
0477
0478 return 0;
0479 }
0480
0481 static int acpi_button_add(struct acpi_device *device)
0482 {
0483 struct acpi_button *button;
0484 struct input_dev *input;
0485 const char *hid = acpi_device_hid(device);
0486 char *name, *class;
0487 int error;
0488
0489 if (!strcmp(hid, ACPI_BUTTON_HID_LID) &&
0490 lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
0491 return -ENODEV;
0492
0493 button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
0494 if (!button)
0495 return -ENOMEM;
0496
0497 device->driver_data = button;
0498
0499 button->input = input = input_allocate_device();
0500 if (!input) {
0501 error = -ENOMEM;
0502 goto err_free_button;
0503 }
0504
0505 name = acpi_device_name(device);
0506 class = acpi_device_class(device);
0507
0508 if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
0509 !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
0510 button->type = ACPI_BUTTON_TYPE_POWER;
0511 strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
0512 sprintf(class, "%s/%s",
0513 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
0514 } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
0515 !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
0516 button->type = ACPI_BUTTON_TYPE_SLEEP;
0517 strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
0518 sprintf(class, "%s/%s",
0519 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
0520 } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
0521 button->type = ACPI_BUTTON_TYPE_LID;
0522 strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
0523 sprintf(class, "%s/%s",
0524 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
0525 input->open = acpi_lid_input_open;
0526 } else {
0527 pr_info("Unsupported hid [%s]\n", hid);
0528 error = -ENODEV;
0529 goto err_free_input;
0530 }
0531
0532 error = acpi_button_add_fs(device);
0533 if (error)
0534 goto err_free_input;
0535
0536 snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
0537
0538 input->name = name;
0539 input->phys = button->phys;
0540 input->id.bustype = BUS_HOST;
0541 input->id.product = button->type;
0542 input->dev.parent = &device->dev;
0543
0544 switch (button->type) {
0545 case ACPI_BUTTON_TYPE_POWER:
0546 input_set_capability(input, EV_KEY, KEY_POWER);
0547 break;
0548
0549 case ACPI_BUTTON_TYPE_SLEEP:
0550 input_set_capability(input, EV_KEY, KEY_SLEEP);
0551 break;
0552
0553 case ACPI_BUTTON_TYPE_LID:
0554 input_set_capability(input, EV_SW, SW_LID);
0555 break;
0556 }
0557
0558 input_set_drvdata(input, device);
0559 error = input_register_device(input);
0560 if (error)
0561 goto err_remove_fs;
0562 if (button->type == ACPI_BUTTON_TYPE_LID) {
0563
0564
0565
0566
0567 lid_device = device;
0568 }
0569
0570 device_init_wakeup(&device->dev, true);
0571 pr_info("%s [%s]\n", name, acpi_device_bid(device));
0572 return 0;
0573
0574 err_remove_fs:
0575 acpi_button_remove_fs(device);
0576 err_free_input:
0577 input_free_device(input);
0578 err_free_button:
0579 kfree(button);
0580 return error;
0581 }
0582
0583 static int acpi_button_remove(struct acpi_device *device)
0584 {
0585 struct acpi_button *button = acpi_driver_data(device);
0586
0587 acpi_button_remove_fs(device);
0588 input_unregister_device(button->input);
0589 kfree(button);
0590 return 0;
0591 }
0592
0593 static int param_set_lid_init_state(const char *val,
0594 const struct kernel_param *kp)
0595 {
0596 int i;
0597
0598 i = sysfs_match_string(lid_init_state_str, val);
0599 if (i < 0)
0600 return i;
0601
0602 lid_init_state = i;
0603 pr_info("Initial lid state set to '%s'\n", lid_init_state_str[i]);
0604 return 0;
0605 }
0606
0607 static int param_get_lid_init_state(char *buf, const struct kernel_param *kp)
0608 {
0609 int i, c = 0;
0610
0611 for (i = 0; i < ARRAY_SIZE(lid_init_state_str); i++)
0612 if (i == lid_init_state)
0613 c += sprintf(buf + c, "[%s] ", lid_init_state_str[i]);
0614 else
0615 c += sprintf(buf + c, "%s ", lid_init_state_str[i]);
0616
0617 buf[c - 1] = '\n';
0618
0619 return c;
0620 }
0621
0622 module_param_call(lid_init_state,
0623 param_set_lid_init_state, param_get_lid_init_state,
0624 NULL, 0644);
0625 MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
0626
0627 static int acpi_button_register_driver(struct acpi_driver *driver)
0628 {
0629 const struct dmi_system_id *dmi_id;
0630
0631 if (lid_init_state == -1) {
0632 dmi_id = dmi_first_match(dmi_lid_quirks);
0633 if (dmi_id)
0634 lid_init_state = (long)dmi_id->driver_data;
0635 else
0636 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
0637 }
0638
0639
0640
0641
0642
0643
0644
0645
0646 if (acpi_disabled)
0647 return 0;
0648
0649 return acpi_bus_register_driver(driver);
0650 }
0651
0652 static void acpi_button_unregister_driver(struct acpi_driver *driver)
0653 {
0654 if (!acpi_disabled)
0655 acpi_bus_unregister_driver(driver);
0656 }
0657
0658 module_driver(acpi_button_driver, acpi_button_register_driver,
0659 acpi_button_unregister_driver);