blob: 870eb5c7516a5b55dbb4fc03f81abec8ae286525 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001/*
2 * button.c - ACPI Button Driver
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21
22#define pr_fmt(fmt) "ACPI: button: " fmt
23
24#include <linux/compiler.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/types.h>
29#include <linux/proc_fs.h>
30#include <linux/seq_file.h>
31#include <linux/input.h>
32#include <linux/slab.h>
33#include <linux/acpi.h>
34#include <linux/dmi.h>
35#include <acpi/button.h>
36
37#define PREFIX "ACPI: "
38
39#define ACPI_BUTTON_CLASS "button"
40#define ACPI_BUTTON_FILE_INFO "info"
41#define ACPI_BUTTON_FILE_STATE "state"
42#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
43#define ACPI_BUTTON_NOTIFY_STATUS 0x80
44
45#define ACPI_BUTTON_SUBCLASS_POWER "power"
46#define ACPI_BUTTON_HID_POWER "PNP0C0C"
47#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button"
48#define ACPI_BUTTON_TYPE_POWER 0x01
49
50#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
51#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
52#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button"
53#define ACPI_BUTTON_TYPE_SLEEP 0x03
54
55#define ACPI_BUTTON_SUBCLASS_LID "lid"
56#define ACPI_BUTTON_HID_LID "PNP0C0D"
57#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
58#define ACPI_BUTTON_TYPE_LID 0x05
59
60#define ACPI_BUTTON_LID_INIT_IGNORE 0x00
61#define ACPI_BUTTON_LID_INIT_OPEN 0x01
62#define ACPI_BUTTON_LID_INIT_METHOD 0x02
63
64#define _COMPONENT ACPI_BUTTON_COMPONENT
65ACPI_MODULE_NAME("button");
66
67MODULE_AUTHOR("Paul Diefenbaugh");
68MODULE_DESCRIPTION("ACPI Button Driver");
69MODULE_LICENSE("GPL");
70
71static const struct acpi_device_id button_device_ids[] = {
72 {ACPI_BUTTON_HID_LID, 0},
73 {ACPI_BUTTON_HID_SLEEP, 0},
74 {ACPI_BUTTON_HID_SLEEPF, 0},
75 {ACPI_BUTTON_HID_POWER, 0},
76 {ACPI_BUTTON_HID_POWERF, 0},
77 {"", 0},
78};
79MODULE_DEVICE_TABLE(acpi, button_device_ids);
80
81/*
82 * Some devices which don't even have a lid in anyway have a broken _LID
83 * method (e.g. pointing to a floating gpio pin) causing spurious LID events.
84 */
85static const struct dmi_system_id lid_blacklst[] = {
86 {
87 /* GP-electronic T701 */
88 .matches = {
89 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
90 DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
91 DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
92 },
93 },
94 {
95 /*
96 * Medion Akoya E2215T, notification of the LID device only
97 * happens on close, not on open and _LID always returns closed.
98 */
99 .matches = {
100 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
101 DMI_MATCH(DMI_PRODUCT_NAME, "E2215T MD60198"),
102 },
103 .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
104 },
105 {}
106};
107
108static int acpi_button_add(struct acpi_device *device);
109static int acpi_button_remove(struct acpi_device *device);
110static void acpi_button_notify(struct acpi_device *device, u32 event);
111
112#ifdef CONFIG_PM_SLEEP
113static int acpi_button_suspend(struct device *dev);
114static int acpi_button_resume(struct device *dev);
115#else
116#define acpi_button_suspend NULL
117#define acpi_button_resume NULL
118#endif
119static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
120
121static struct acpi_driver acpi_button_driver = {
122 .name = "button",
123 .class = ACPI_BUTTON_CLASS,
124 .ids = button_device_ids,
125 .ops = {
126 .add = acpi_button_add,
127 .remove = acpi_button_remove,
128 .notify = acpi_button_notify,
129 },
130 .drv.pm = &acpi_button_pm,
131};
132
133struct acpi_button {
134 unsigned int type;
135 struct input_dev *input;
136 char phys[32]; /* for input device */
137 unsigned long pushed;
138 int last_state;
139 ktime_t last_time;
140 bool suspended;
141};
142
143static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
144static struct acpi_device *lid_device;
145static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
146
147static unsigned long lid_report_interval __read_mostly = 500;
148module_param(lid_report_interval, ulong, 0644);
149MODULE_PARM_DESC(lid_report_interval, "Interval (ms) between lid key events");
150
151/* --------------------------------------------------------------------------
152 FS Interface (/proc)
153 -------------------------------------------------------------------------- */
154
155static struct proc_dir_entry *acpi_button_dir;
156static struct proc_dir_entry *acpi_lid_dir;
157
158static int acpi_lid_evaluate_state(struct acpi_device *device)
159{
160 unsigned long long lid_state;
161 acpi_status status;
162
163 status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state);
164 if (ACPI_FAILURE(status))
165 return -ENODEV;
166
167 return lid_state ? 1 : 0;
168}
169
170static int acpi_lid_notify_state(struct acpi_device *device, int state)
171{
172 struct acpi_button *button = acpi_driver_data(device);
173 int ret;
174 ktime_t next_report;
175 bool do_update;
176
177 /*
178 * In lid_init_state=ignore mode, if user opens/closes lid
179 * frequently with "open" missing, and "last_time" is also updated
180 * frequently, "close" cannot be delivered to the userspace.
181 * So "last_time" is only updated after a timeout or an actual
182 * switch.
183 */
184 if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE ||
185 button->last_state != !!state)
186 do_update = true;
187 else
188 do_update = false;
189
190 next_report = ktime_add(button->last_time,
191 ms_to_ktime(lid_report_interval));
192 if (button->last_state == !!state &&
193 ktime_after(ktime_get(), next_report)) {
194 /* Complain the buggy firmware */
195 pr_warn_once("The lid device is not compliant to SW_LID.\n");
196
197 /*
198 * Send the unreliable complement switch event:
199 *
200 * On most platforms, the lid device is reliable. However
201 * there are exceptions:
202 * 1. Platforms returning initial lid state as "close" by
203 * default after booting/resuming:
204 * https://bugzilla.kernel.org/show_bug.cgi?id=89211
205 * https://bugzilla.kernel.org/show_bug.cgi?id=106151
206 * 2. Platforms never reporting "open" events:
207 * https://bugzilla.kernel.org/show_bug.cgi?id=106941
208 * On these buggy platforms, the usage model of the ACPI
209 * lid device actually is:
210 * 1. The initial returning value of _LID may not be
211 * reliable.
212 * 2. The open event may not be reliable.
213 * 3. The close event is reliable.
214 *
215 * But SW_LID is typed as input switch event, the input
216 * layer checks if the event is redundant. Hence if the
217 * state is not switched, the userspace cannot see this
218 * platform triggered reliable event. By inserting a
219 * complement switch event, it then is guaranteed that the
220 * platform triggered reliable one can always be seen by
221 * the userspace.
222 */
223 if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) {
224 do_update = true;
225 /*
226 * Do generate complement switch event for "close"
227 * as "close" is reliable and wrong "open" won't
228 * trigger unexpected behaviors.
229 * Do not generate complement switch event for
230 * "open" as "open" is not reliable and wrong
231 * "close" will trigger unexpected behaviors.
232 */
233 if (!state) {
234 input_report_switch(button->input,
235 SW_LID, state);
236 input_sync(button->input);
237 }
238 }
239 }
240 /* Send the platform triggered reliable event */
241 if (do_update) {
242 acpi_handle_debug(device->handle, "ACPI LID %s\n",
243 state ? "open" : "closed");
244 input_report_switch(button->input, SW_LID, !state);
245 input_sync(button->input);
246 button->last_state = !!state;
247 button->last_time = ktime_get();
248 }
249
250 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
251 if (ret == NOTIFY_DONE)
252 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
253 device);
254 if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
255 /*
256 * It is also regarded as success if the notifier_chain
257 * returns NOTIFY_OK or NOTIFY_DONE.
258 */
259 ret = 0;
260 }
261 return ret;
262}
263
264static int __maybe_unused acpi_button_state_seq_show(struct seq_file *seq,
265 void *offset)
266{
267 struct acpi_device *device = seq->private;
268 int state;
269
270 state = acpi_lid_evaluate_state(device);
271 seq_printf(seq, "state: %s\n",
272 state < 0 ? "unsupported" : (state ? "open" : "closed"));
273 return 0;
274}
275
276static int acpi_button_add_fs(struct acpi_device *device)
277{
278 struct acpi_button *button = acpi_driver_data(device);
279 struct proc_dir_entry *entry = NULL;
280 int ret = 0;
281
282 /* procfs I/F for ACPI lid device only */
283 if (button->type != ACPI_BUTTON_TYPE_LID)
284 return 0;
285
286 if (acpi_button_dir || acpi_lid_dir) {
287 printk(KERN_ERR PREFIX "More than one Lid device found!\n");
288 return -EEXIST;
289 }
290
291 /* create /proc/acpi/button */
292 acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
293 if (!acpi_button_dir)
294 return -ENODEV;
295
296 /* create /proc/acpi/button/lid */
297 acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
298 if (!acpi_lid_dir) {
299 ret = -ENODEV;
300 goto remove_button_dir;
301 }
302
303 /* create /proc/acpi/button/lid/LID/ */
304 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
305 if (!acpi_device_dir(device)) {
306 ret = -ENODEV;
307 goto remove_lid_dir;
308 }
309
310 /* create /proc/acpi/button/lid/LID/state */
311 entry = proc_create_single_data(ACPI_BUTTON_FILE_STATE, S_IRUGO,
312 acpi_device_dir(device), acpi_button_state_seq_show,
313 device);
314 if (!entry) {
315 ret = -ENODEV;
316 goto remove_dev_dir;
317 }
318
319done:
320 return ret;
321
322remove_dev_dir:
323 remove_proc_entry(acpi_device_bid(device),
324 acpi_lid_dir);
325 acpi_device_dir(device) = NULL;
326remove_lid_dir:
327 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
328 acpi_lid_dir = NULL;
329remove_button_dir:
330 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
331 acpi_button_dir = NULL;
332 goto done;
333}
334
335static int acpi_button_remove_fs(struct acpi_device *device)
336{
337 struct acpi_button *button = acpi_driver_data(device);
338
339 if (button->type != ACPI_BUTTON_TYPE_LID)
340 return 0;
341
342 remove_proc_entry(ACPI_BUTTON_FILE_STATE,
343 acpi_device_dir(device));
344 remove_proc_entry(acpi_device_bid(device),
345 acpi_lid_dir);
346 acpi_device_dir(device) = NULL;
347 remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
348 acpi_lid_dir = NULL;
349 remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
350 acpi_button_dir = NULL;
351
352 return 0;
353}
354
355/* --------------------------------------------------------------------------
356 Driver Interface
357 -------------------------------------------------------------------------- */
358int acpi_lid_notifier_register(struct notifier_block *nb)
359{
360 return blocking_notifier_chain_register(&acpi_lid_notifier, nb);
361}
362EXPORT_SYMBOL(acpi_lid_notifier_register);
363
364int acpi_lid_notifier_unregister(struct notifier_block *nb)
365{
366 return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb);
367}
368EXPORT_SYMBOL(acpi_lid_notifier_unregister);
369
370int acpi_lid_open(void)
371{
372 if (!lid_device)
373 return -ENODEV;
374
375 return acpi_lid_evaluate_state(lid_device);
376}
377EXPORT_SYMBOL(acpi_lid_open);
378
379static int acpi_lid_update_state(struct acpi_device *device,
380 bool signal_wakeup)
381{
382 int state;
383
384 state = acpi_lid_evaluate_state(device);
385 if (state < 0)
386 return state;
387
388 if (state && signal_wakeup)
389 acpi_pm_wakeup_event(&device->dev);
390
391 return acpi_lid_notify_state(device, state);
392}
393
394static void acpi_lid_initialize_state(struct acpi_device *device)
395{
396 switch (lid_init_state) {
397 case ACPI_BUTTON_LID_INIT_OPEN:
398 (void)acpi_lid_notify_state(device, 1);
399 break;
400 case ACPI_BUTTON_LID_INIT_METHOD:
401 (void)acpi_lid_update_state(device, false);
402 break;
403 case ACPI_BUTTON_LID_INIT_IGNORE:
404 default:
405 break;
406 }
407}
408
409static void acpi_button_notify(struct acpi_device *device, u32 event)
410{
411 struct acpi_button *button = acpi_driver_data(device);
412 struct input_dev *input;
413 int users;
414
415 switch (event) {
416 case ACPI_FIXED_HARDWARE_EVENT:
417 event = ACPI_BUTTON_NOTIFY_STATUS;
418 /* fall through */
419 case ACPI_BUTTON_NOTIFY_STATUS:
420 input = button->input;
421 if (button->type == ACPI_BUTTON_TYPE_LID) {
422 mutex_lock(&button->input->mutex);
423 users = button->input->users;
424 mutex_unlock(&button->input->mutex);
425 if (users)
426 acpi_lid_update_state(device, true);
427 } else {
428 int keycode;
429
430 acpi_pm_wakeup_event(&device->dev);
431 if (button->suspended)
432 break;
433
434 keycode = test_bit(KEY_SLEEP, input->keybit) ?
435 KEY_SLEEP : KEY_POWER;
436 input_report_key(input, keycode, 1);
437 input_sync(input);
438 input_report_key(input, keycode, 0);
439 input_sync(input);
440
441 acpi_bus_generate_netlink_event(
442 device->pnp.device_class,
443 dev_name(&device->dev),
444 event, ++button->pushed);
445 }
446 break;
447 default:
448 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
449 "Unsupported event [0x%x]\n", event));
450 break;
451 }
452}
453
454#ifdef CONFIG_PM_SLEEP
455static int acpi_button_suspend(struct device *dev)
456{
457 struct acpi_device *device = to_acpi_device(dev);
458 struct acpi_button *button = acpi_driver_data(device);
459
460 button->suspended = true;
461 return 0;
462}
463
464static int acpi_button_resume(struct device *dev)
465{
466 struct acpi_device *device = to_acpi_device(dev);
467 struct acpi_button *button = acpi_driver_data(device);
468
469 button->suspended = false;
470 if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users)
471 acpi_lid_initialize_state(device);
472 return 0;
473}
474#endif
475
476static int acpi_lid_input_open(struct input_dev *input)
477{
478 struct acpi_device *device = input_get_drvdata(input);
479 struct acpi_button *button = acpi_driver_data(device);
480
481 button->last_state = !!acpi_lid_evaluate_state(device);
482 button->last_time = ktime_get();
483 acpi_lid_initialize_state(device);
484
485 return 0;
486}
487
488static int acpi_button_add(struct acpi_device *device)
489{
490 struct acpi_button *button;
491 struct input_dev *input;
492 const char *hid = acpi_device_hid(device);
493 char *name, *class;
494 int error;
495
496 if (!strcmp(hid, ACPI_BUTTON_HID_LID) && dmi_check_system(lid_blacklst))
497 return -ENODEV;
498
499 button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
500 if (!button)
501 return -ENOMEM;
502
503 device->driver_data = button;
504
505 button->input = input = input_allocate_device();
506 if (!input) {
507 error = -ENOMEM;
508 goto err_free_button;
509 }
510
511 name = acpi_device_name(device);
512 class = acpi_device_class(device);
513
514 if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
515 !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
516 button->type = ACPI_BUTTON_TYPE_POWER;
517 strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
518 sprintf(class, "%s/%s",
519 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
520 } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
521 !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
522 button->type = ACPI_BUTTON_TYPE_SLEEP;
523 strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
524 sprintf(class, "%s/%s",
525 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
526 } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
527 button->type = ACPI_BUTTON_TYPE_LID;
528 strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
529 sprintf(class, "%s/%s",
530 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
531 input->open = acpi_lid_input_open;
532 } else {
533 printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
534 error = -ENODEV;
535 goto err_free_input;
536 }
537
538 error = acpi_button_add_fs(device);
539 if (error)
540 goto err_free_input;
541
542 snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
543
544 input->name = name;
545 input->phys = button->phys;
546 input->id.bustype = BUS_HOST;
547 input->id.product = button->type;
548 input->dev.parent = &device->dev;
549
550 switch (button->type) {
551 case ACPI_BUTTON_TYPE_POWER:
552 input_set_capability(input, EV_KEY, KEY_POWER);
553 break;
554
555 case ACPI_BUTTON_TYPE_SLEEP:
556 input_set_capability(input, EV_KEY, KEY_SLEEP);
557 break;
558
559 case ACPI_BUTTON_TYPE_LID:
560 input_set_capability(input, EV_SW, SW_LID);
561 break;
562 }
563
564 input_set_drvdata(input, device);
565 error = input_register_device(input);
566 if (error)
567 goto err_remove_fs;
568 if (button->type == ACPI_BUTTON_TYPE_LID) {
569 /*
570 * This assumes there's only one lid device, or if there are
571 * more we only care about the last one...
572 */
573 lid_device = device;
574 }
575
576 device_init_wakeup(&device->dev, true);
577 printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
578 return 0;
579
580 err_remove_fs:
581 acpi_button_remove_fs(device);
582 err_free_input:
583 input_free_device(input);
584 err_free_button:
585 kfree(button);
586 return error;
587}
588
589static int acpi_button_remove(struct acpi_device *device)
590{
591 struct acpi_button *button = acpi_driver_data(device);
592
593 acpi_button_remove_fs(device);
594 input_unregister_device(button->input);
595 kfree(button);
596 return 0;
597}
598
599static int param_set_lid_init_state(const char *val,
600 const struct kernel_param *kp)
601{
602 int result = 0;
603
604 if (!strncmp(val, "open", sizeof("open") - 1)) {
605 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
606 pr_info("Notify initial lid state as open\n");
607 } else if (!strncmp(val, "method", sizeof("method") - 1)) {
608 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
609 pr_info("Notify initial lid state with _LID return value\n");
610 } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
611 lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
612 pr_info("Do not notify initial lid state\n");
613 } else
614 result = -EINVAL;
615 return result;
616}
617
618static int param_get_lid_init_state(char *buffer,
619 const struct kernel_param *kp)
620{
621 switch (lid_init_state) {
622 case ACPI_BUTTON_LID_INIT_OPEN:
623 return sprintf(buffer, "open");
624 case ACPI_BUTTON_LID_INIT_METHOD:
625 return sprintf(buffer, "method");
626 case ACPI_BUTTON_LID_INIT_IGNORE:
627 return sprintf(buffer, "ignore");
628 default:
629 return sprintf(buffer, "invalid");
630 }
631 return 0;
632}
633
634module_param_call(lid_init_state,
635 param_set_lid_init_state, param_get_lid_init_state,
636 NULL, 0644);
637MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state");
638
639static int acpi_button_register_driver(struct acpi_driver *driver)
640{
641 /*
642 * Modules such as nouveau.ko and i915.ko have a link time dependency
643 * on acpi_lid_open(), and would therefore not be loadable on ACPI
644 * capable kernels booted in non-ACPI mode if the return value of
645 * acpi_bus_register_driver() is returned from here with ACPI disabled
646 * when this driver is built as a module.
647 */
648 if (acpi_disabled)
649 return 0;
650
651 return acpi_bus_register_driver(driver);
652}
653
654static void acpi_button_unregister_driver(struct acpi_driver *driver)
655{
656 if (!acpi_disabled)
657 acpi_bus_unregister_driver(driver);
658}
659
660module_driver(acpi_button_driver, acpi_button_register_driver,
661 acpi_button_unregister_driver);